diff mbox series

[1/2] libinput: upgrade 1.30.2 -> 1.30.4

Message ID 20260616111643.4091790-1-ross.burton@arm.com
State Under Review
Headers show
Series [1/2] libinput: upgrade 1.30.2 -> 1.30.4 | expand

Commit Message

Ross Burton June 16, 2026, 11:16 a.m. UTC
libinput 1.30.3:

This release contains just the CVE patches that we backported.

libinput 1.30.4:

This release contains a fix for todays security advisory: CVE-2026-50265.
libinput-device-group now sanitizes the PHYS value which prevents local
privilege escalation through udev property injection. As said in the advisory
this is only a security issue if you have a udev rule in place that allows
users to create uinput devices.

Signed-off-by: Ross Burton <ross.burton@arm.com>
---
 .../wayland/libinput/CVE-2026-35093.patch     | 124 ------------
 .../wayland/libinput/CVE-2026-35094.patch     | 191 ------------------
 ...{libinput_1.30.2.bb => libinput_1.30.4.bb} |   4 +-
 3 files changed, 1 insertion(+), 318 deletions(-)
 delete mode 100644 meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
 delete mode 100644 meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
 rename meta/recipes-graphics/wayland/{libinput_1.30.2.bb => libinput_1.30.4.bb} (93%)

Comments

Ross Burton June 16, 2026, 11:18 a.m. UTC | #1
Note that I sent this as two upgrades because the 1.30.4 upgrade is a good candidate for the wrynose branch as the only commits since 1.30.4 are CVE fixes.

Ross

> On 16 Jun 2026, at 12:16, Ross Burton via lists.openembedded.org <ross.burton=arm.com@lists.openembedded.org> wrote:
> 
> libinput 1.30.3:
> 
> This release contains just the CVE patches that we backported.
> 
> libinput 1.30.4:
> 
> This release contains a fix for todays security advisory: CVE-2026-50265.
> libinput-device-group now sanitizes the PHYS value which prevents local
> privilege escalation through udev property injection. As said in the advisory
> this is only a security issue if you have a udev rule in place that allows
> users to create uinput devices.
> 
> Signed-off-by: Ross Burton <ross.burton@arm.com>
> ---
> .../wayland/libinput/CVE-2026-35093.patch     | 124 ------------
> .../wayland/libinput/CVE-2026-35094.patch     | 191 ------------------
> ...{libinput_1.30.2.bb => libinput_1.30.4.bb} |   4 +-
> 3 files changed, 1 insertion(+), 318 deletions(-)
> delete mode 100644 meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> delete mode 100644 meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> rename meta/recipes-graphics/wayland/{libinput_1.30.2.bb => libinput_1.30.4.bb} (93%)
> 
> diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch b/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> deleted file mode 100644
> index e0119caaca1..00000000000
> --- a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> +++ /dev/null
> @@ -1,124 +0,0 @@
> -From 356c498fd4ba25ec99f6866fc96847ec3d1f16bf Mon Sep 17 00:00:00 2001
> -From: Peter Hutterer <peter.hutterer@who-t.net>
> -Date: Mon, 30 Mar 2026 11:35:35 +1000
> -Subject: [PATCH] lua: force text mode for loading plugins
> -
> -luaL_loadfile() by default allows for both text files and precompiled
> -lua files. Precompiled files are not verified on load allowing for a
> -sandbox escape.
> -
> -CVE-2026-35093
> -
> -Fixes: #1271
> -
> -Found-by: Koen Tange <koen@monokles.eu>
> -Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
> -
> -CVE: CVE-2025-35093
> -Upstream-Status: Backport
> -Signed-off-by: Ross Burton <ross.burton@arm.com>
> ----
> - src/libinput-plugin-lua.c |  2 +-
> - test/test-plugins-lua.c   | 69 +++++++++++++++++++++++++++++++++++++++
> - 2 files changed, 70 insertions(+), 1 deletion(-)
> -
> -diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c
> -index c6f99a5f..2a09a64a 100644
> ---- a/src/libinput-plugin-lua.c
> -+++ b/src/libinput-plugin-lua.c
> -@@ -1362,7 +1362,7 @@ libinput_lua_plugin_new_from_path(struct libinput *libinput, const char *path)
> - return NULL;
> - }
> - 
> -- int ret = luaL_loadfile(L, path);
> -+ int ret = luaL_loadfilex(L, path, "t");
> - if (ret == LUA_OK) {
> - plugin->L = steal(&L);
> - 
> -diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c
> -index aba8f6c6..e61806d3 100644
> ---- a/test/test-plugins-lua.c
> -+++ b/test/test-plugins-lua.c
> -@@ -1204,10 +1204,79 @@ START_TEST(lua_remove_plugin_on_timeout)
> - }
> - 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),
> --- 
> -GitLab
> -
> diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch b/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> deleted file mode 100644
> index 405a262b03e..00000000000
> --- a/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> +++ /dev/null
> @@ -1,191 +0,0 @@
> -From 45dfd0f0301af855f068df27b2e40cc9f5713acd Mon Sep 17 00:00:00 2001
> -From: Peter Hutterer <peter.hutterer@who-t.net>
> -Date: Mon, 30 Mar 2026 09:41:08 +1000
> -Subject: [PATCH] lua: separate the API from the metatables
> -
> -Previously we had one vtable for the libinputplugin and EvdevDevice
> -objects. This allowed plugins to call __gc(), a decidedly internal
> -method.
> -
> -This fixes a use-after-free: A plugin that called EvdevDevice::__gc()
> -frees the plugin's copy of device->name but leaves the pointer in-place,
> -a subsequent call will thus cause a UAF read.
> -
> -Fix this by separating what is the object's metatable from the public
> -methods that are accessible to a plugin.
> -
> -CVE-2026-35094
> -
> -Fixes: #1272
> -
> -Found-by: Koen Tange <koen@monokles.eu>
> -Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
> -
> -CVE: CVE-2025-35094
> -Upstream-Status: Backport
> -Signed-off-by: Ross Burton <ross.burton@arm.com>
> -
> ----
> - src/libinput-plugin-lua.c | 54 +++++++++++++++++++++++++++++----------
> - test/test-plugins-lua.c   | 33 ++++++++++++++++++++++++
> - 2 files changed, 73 insertions(+), 14 deletions(-)
> -
> -diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c
> -index ac828f7f..c6f99a5f 100644
> ---- a/src/libinput-plugin-lua.c
> -+++ b/src/libinput-plugin-lua.c
> -@@ -562,6 +562,12 @@ libinputplugin_unregister(lua_State *L)
> - return luaL_error(L, "@@unregistering@@");
> - }
> - 
> -+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)
> - {
> -@@ -673,7 +679,28 @@ libinputplugin_log_error(lua_State *L)
> - 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 @@ static const struct luaL_Reg libinputplugin_vtable[] = {
> - { "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 @@ evdevdevice_gc(lua_State *L)
> - 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 @@ static const struct luaL_Reg evdevdevice_vtable[] = {
> - { "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
> -diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c
> -index 4d687203..aba8f6c6 100644
> ---- a/test/test-plugins-lua.c
> -+++ b/test/test-plugins-lua.c
> -@@ -526,6 +526,38 @@ START_TEST(lua_disallowed_functions)
> - }
> - 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);
> -@@ -1219,6 +1251,7 @@ TEST_COLLECTION(lua)
> - 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);
> --- 
> -GitLab
> -
> diff --git a/meta/recipes-graphics/wayland/libinput_1.30.2.bb b/meta/recipes-graphics/wayland/libinput_1.30.4.bb
> similarity index 93%
> rename from meta/recipes-graphics/wayland/libinput_1.30.2.bb
> rename to meta/recipes-graphics/wayland/libinput_1.30.4.bb
> index efd51809d8e..8ce3d0d62cf 100644
> --- a/meta/recipes-graphics/wayland/libinput_1.30.2.bb
> +++ b/meta/recipes-graphics/wayland/libinput_1.30.4.bb
> @@ -13,11 +13,9 @@ LIC_FILES_CHKSUM = "file://COPYING;md5=bab4ac7dc1c10bc0fb037dc76c46ef8a"
> DEPENDS = "libevdev udev"
> 
> SRC_URI = "git://gitlab.freedesktop.org/libinput/libinput.git;protocol=https;branch=1.30-branch;tag=${PV} \
> -           file://CVE-2026-35093.patch \
> -           file://CVE-2026-35094.patch \
>            file://run-ptest \
>            "
> -SRCREV = "042c5e6fd9cc910307027a1522453794b29f2c72"
> +SRCREV = "7ad8b37ffcc71aceb8eb4d079d22490e87168f49"
> 
> UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+\.\d+\.(?!9\d+)\d+)"
> 
> -- 
> 2.43.0
> 
> 
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#238890): https://lists.openembedded.org/g/openembedded-core/message/238890
> Mute This Topic: https://lists.openembedded.org/mt/119831384/6875888
> Group Owner: openembedded-core+owner@lists.openembedded.org
> Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [ross.burton@arm.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Yoann Congal June 16, 2026, 11:22 a.m. UTC | #2
Le mar. 16 juin 2026 à 13:19, Ross Burton <Ross.Burton@arm.com> a écrit :

> Note that I sent this as two upgrades because the 1.30.4 upgrade is a good
> candidate for the wrynose branch as the only commits since 1.30.4 are CVE
> fixes.
>

Thanks Ross,
I've noted to check that after the master merge.


>
> Ross
>
> > On 16 Jun 2026, at 12:16, Ross Burton via lists.openembedded.org
> <ross.burton=arm.com@lists.openembedded.org> wrote:
> >
> > libinput 1.30.3:
> >
> > This release contains just the CVE patches that we backported.
> >
> > libinput 1.30.4:
> >
> > This release contains a fix for todays security advisory: CVE-2026-50265.
> > libinput-device-group now sanitizes the PHYS value which prevents local
> > privilege escalation through udev property injection. As said in the
> advisory
> > this is only a security issue if you have a udev rule in place that
> allows
> > users to create uinput devices.
> >
> > Signed-off-by: Ross Burton <ross.burton@arm.com>
> > ---
> > .../wayland/libinput/CVE-2026-35093.patch     | 124 ------------
> > .../wayland/libinput/CVE-2026-35094.patch     | 191 ------------------
> > ...{libinput_1.30.2.bb => libinput_1.30.4.bb} |   4 +-
> > 3 files changed, 1 insertion(+), 318 deletions(-)
> > delete mode 100644
> meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> > delete mode 100644
> meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> > rename meta/recipes-graphics/wayland/{libinput_1.30.2.bb =>
> libinput_1.30.4.bb} (93%)
> >
> > diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> b/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> > deleted file mode 100644
> > index e0119caaca1..00000000000
> > --- a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
> > +++ /dev/null
> > @@ -1,124 +0,0 @@
> > -From 356c498fd4ba25ec99f6866fc96847ec3d1f16bf Mon Sep 17 00:00:00 2001
> > -From: Peter Hutterer <peter.hutterer@who-t.net>
> > -Date: Mon, 30 Mar 2026 11:35:35 +1000
> > -Subject: [PATCH] lua: force text mode for loading plugins
> > -
> > -luaL_loadfile() by default allows for both text files and precompiled
> > -lua files. Precompiled files are not verified on load allowing for a
> > -sandbox escape.
> > -
> > -CVE-2026-35093
> > -
> > -Fixes: #1271
> > -
> > -Found-by: Koen Tange <koen@monokles.eu>
> > -Part-of: <
> https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
> > -
> > -CVE: CVE-2025-35093
> > -Upstream-Status: Backport
> > -Signed-off-by: Ross Burton <ross.burton@arm.com>
> > ----
> > - src/libinput-plugin-lua.c |  2 +-
> > - test/test-plugins-lua.c   | 69 +++++++++++++++++++++++++++++++++++++++
> > - 2 files changed, 70 insertions(+), 1 deletion(-)
> > -
> > -diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c
> > -index c6f99a5f..2a09a64a 100644
> > ---- a/src/libinput-plugin-lua.c
> > -+++ b/src/libinput-plugin-lua.c
> > -@@ -1362,7 +1362,7 @@ libinput_lua_plugin_new_from_path(struct libinput
> *libinput, const char *path)
> > - return NULL;
> > - }
> > -
> > -- int ret = luaL_loadfile(L, path);
> > -+ int ret = luaL_loadfilex(L, path, "t");
> > - if (ret == LUA_OK) {
> > - plugin->L = steal(&L);
> > -
> > -diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c
> > -index aba8f6c6..e61806d3 100644
> > ---- a/test/test-plugins-lua.c
> > -+++ b/test/test-plugins-lua.c
> > -@@ -1204,10 +1204,79 @@ START_TEST(lua_remove_plugin_on_timeout)
> > - }
> > - 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),
> > ---
> > -GitLab
> > -
> > diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> b/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> > deleted file mode 100644
> > index 405a262b03e..00000000000
> > --- a/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
> > +++ /dev/null
> > @@ -1,191 +0,0 @@
> > -From 45dfd0f0301af855f068df27b2e40cc9f5713acd Mon Sep 17 00:00:00 2001
> > -From: Peter Hutterer <peter.hutterer@who-t.net>
> > -Date: Mon, 30 Mar 2026 09:41:08 +1000
> > -Subject: [PATCH] lua: separate the API from the metatables
> > -
> > -Previously we had one vtable for the libinputplugin and EvdevDevice
> > -objects. This allowed plugins to call __gc(), a decidedly internal
> > -method.
> > -
> > -This fixes a use-after-free: A plugin that called EvdevDevice::__gc()
> > -frees the plugin's copy of device->name but leaves the pointer in-place,
> > -a subsequent call will thus cause a UAF read.
> > -
> > -Fix this by separating what is the object's metatable from the public
> > -methods that are accessible to a plugin.
> > -
> > -CVE-2026-35094
> > -
> > -Fixes: #1272
> > -
> > -Found-by: Koen Tange <koen@monokles.eu>
> > -Part-of: <
> https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
> > -
> > -CVE: CVE-2025-35094
> > -Upstream-Status: Backport
> > -Signed-off-by: Ross Burton <ross.burton@arm.com>
> > -
> > ----
> > - src/libinput-plugin-lua.c | 54 +++++++++++++++++++++++++++++----------
> > - test/test-plugins-lua.c   | 33 ++++++++++++++++++++++++
> > - 2 files changed, 73 insertions(+), 14 deletions(-)
> > -
> > -diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c
> > -index ac828f7f..c6f99a5f 100644
> > ---- a/src/libinput-plugin-lua.c
> > -+++ b/src/libinput-plugin-lua.c
> > -@@ -562,6 +562,12 @@ libinputplugin_unregister(lua_State *L)
> > - return luaL_error(L, "@@unregistering@@");
> > - }
> > -
> > -+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)
> > - {
> > -@@ -673,7 +679,28 @@ libinputplugin_log_error(lua_State *L)
> > - 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 @@ static const struct luaL_Reg
> libinputplugin_vtable[] = {
> > - { "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 @@ evdevdevice_gc(lua_State *L)
> > - 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 @@ static const struct luaL_Reg
> evdevdevice_vtable[] = {
> > - { "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
> > -diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c
> > -index 4d687203..aba8f6c6 100644
> > ---- a/test/test-plugins-lua.c
> > -+++ b/test/test-plugins-lua.c
> > -@@ -526,6 +526,38 @@ START_TEST(lua_disallowed_functions)
> > - }
> > - 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);
> > -@@ -1219,6 +1251,7 @@ TEST_COLLECTION(lua)
> > - 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);
> > ---
> > -GitLab
> > -
> > diff --git a/meta/recipes-graphics/wayland/libinput_1.30.2.bb
> b/meta/recipes-graphics/wayland/libinput_1.30.4.bb
> > similarity index 93%
> > rename from meta/recipes-graphics/wayland/libinput_1.30.2.bb
> > rename to meta/recipes-graphics/wayland/libinput_1.30.4.bb
> > index efd51809d8e..8ce3d0d62cf 100644
> > --- a/meta/recipes-graphics/wayland/libinput_1.30.2.bb
> > +++ b/meta/recipes-graphics/wayland/libinput_1.30.4.bb
> > @@ -13,11 +13,9 @@ LIC_FILES_CHKSUM =
> "file://COPYING;md5=bab4ac7dc1c10bc0fb037dc76c46ef8a"
> > DEPENDS = "libevdev udev"
> >
> > SRC_URI = "git://
> gitlab.freedesktop.org/libinput/libinput.git;protocol=https;branch=1.30-branch;tag=${PV}
> <http://gitlab.freedesktop.org/libinput/libinput.git;protocol=https;branch=1.30-branch;tag=$%7BPV%7D>
> \
> > -           file://CVE-2026-35093.patch \
> > -           file://CVE-2026-35094.patch \
> >            file://run-ptest \
> >            "
> > -SRCREV = "042c5e6fd9cc910307027a1522453794b29f2c72"
> > +SRCREV = "7ad8b37ffcc71aceb8eb4d079d22490e87168f49"
> >
> > UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+\.\d+\.(?!9\d+)\d+)"
> >
> > --
> > 2.43.0
> >
> >
> > -=-=-=-=-=-=-=-=-=-=-=-
> > Links: You receive all messages sent to this group.
> > View/Reply Online (#238890):
> https://lists.openembedded.org/g/openembedded-core/message/238890
> > Mute This Topic: https://lists.openembedded.org/mt/119831384/6875888
> > Group Owner: openembedded-core+owner@lists.openembedded.org
> > Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub [
> ross.burton@arm.com]
> > -=-=-=-=-=-=-=-=-=-=-=-
> >
>
>
diff mbox series

Patch

diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch b/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
deleted file mode 100644
index e0119caaca1..00000000000
--- a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch
+++ /dev/null
@@ -1,124 +0,0 @@ 
-From 356c498fd4ba25ec99f6866fc96847ec3d1f16bf Mon Sep 17 00:00:00 2001
-From: Peter Hutterer <peter.hutterer@who-t.net>
-Date: Mon, 30 Mar 2026 11:35:35 +1000
-Subject: [PATCH] lua: force text mode for loading plugins
-
-luaL_loadfile() by default allows for both text files and precompiled
-lua files. Precompiled files are not verified on load allowing for a
-sandbox escape.
-
-CVE-2026-35093
-
-Fixes: #1271
-
-Found-by: Koen Tange <koen@monokles.eu>
-Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
-
-CVE: CVE-2025-35093
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
----
- src/libinput-plugin-lua.c |  2 +-
- test/test-plugins-lua.c   | 69 +++++++++++++++++++++++++++++++++++++++
- 2 files changed, 70 insertions(+), 1 deletion(-)
-
-diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c
-index c6f99a5f..2a09a64a 100644
---- a/src/libinput-plugin-lua.c
-+++ b/src/libinput-plugin-lua.c
-@@ -1362,7 +1362,7 @@ libinput_lua_plugin_new_from_path(struct libinput *libinput, const char *path)
- 		return NULL;
- 	}
- 
--	int ret = luaL_loadfile(L, path);
-+	int ret = luaL_loadfilex(L, path, "t");
- 	if (ret == LUA_OK) {
- 		plugin->L = steal(&L);
- 
-diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c
-index aba8f6c6..e61806d3 100644
---- a/test/test-plugins-lua.c
-+++ b/test/test-plugins-lua.c
-@@ -1204,10 +1204,79 @@ START_TEST(lua_remove_plugin_on_timeout)
- }
- 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),
--- 
-GitLab
-
diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch b/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
deleted file mode 100644
index 405a262b03e..00000000000
--- a/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch
+++ /dev/null
@@ -1,191 +0,0 @@ 
-From 45dfd0f0301af855f068df27b2e40cc9f5713acd Mon Sep 17 00:00:00 2001
-From: Peter Hutterer <peter.hutterer@who-t.net>
-Date: Mon, 30 Mar 2026 09:41:08 +1000
-Subject: [PATCH] lua: separate the API from the metatables
-
-Previously we had one vtable for the libinputplugin and EvdevDevice
-objects. This allowed plugins to call __gc(), a decidedly internal
-method.
-
-This fixes a use-after-free: A plugin that called EvdevDevice::__gc()
-frees the plugin's copy of device->name but leaves the pointer in-place,
-a subsequent call will thus cause a UAF read.
-
-Fix this by separating what is the object's metatable from the public
-methods that are accessible to a plugin.
-
-CVE-2026-35094
-
-Fixes: #1272
-
-Found-by: Koen Tange <koen@monokles.eu>
-Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1459>
-
-CVE: CVE-2025-35094
-Upstream-Status: Backport
-Signed-off-by: Ross Burton <ross.burton@arm.com>
-
----
- src/libinput-plugin-lua.c | 54 +++++++++++++++++++++++++++++----------
- test/test-plugins-lua.c   | 33 ++++++++++++++++++++++++
- 2 files changed, 73 insertions(+), 14 deletions(-)
-
-diff --git a/src/libinput-plugin-lua.c b/src/libinput-plugin-lua.c
-index ac828f7f..c6f99a5f 100644
---- a/src/libinput-plugin-lua.c
-+++ b/src/libinput-plugin-lua.c
-@@ -562,6 +562,12 @@ libinputplugin_unregister(lua_State *L)
- 	return luaL_error(L, "@@unregistering@@");
- }
- 
-+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)
- {
-@@ -673,7 +679,28 @@ libinputplugin_log_error(lua_State *L)
- 	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 @@ static const struct luaL_Reg libinputplugin_vtable[] = {
- 	{ "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 @@ evdevdevice_gc(lua_State *L)
- 	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 @@ static const struct luaL_Reg evdevdevice_vtable[] = {
- 	{ "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
-diff --git a/test/test-plugins-lua.c b/test/test-plugins-lua.c
-index 4d687203..aba8f6c6 100644
---- a/test/test-plugins-lua.c
-+++ b/test/test-plugins-lua.c
-@@ -526,6 +526,38 @@ START_TEST(lua_disallowed_functions)
- }
- 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);
-@@ -1219,6 +1251,7 @@ TEST_COLLECTION(lua)
- 	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);
--- 
-GitLab
-
diff --git a/meta/recipes-graphics/wayland/libinput_1.30.2.bb b/meta/recipes-graphics/wayland/libinput_1.30.4.bb
similarity index 93%
rename from meta/recipes-graphics/wayland/libinput_1.30.2.bb
rename to meta/recipes-graphics/wayland/libinput_1.30.4.bb
index efd51809d8e..8ce3d0d62cf 100644
--- a/meta/recipes-graphics/wayland/libinput_1.30.2.bb
+++ b/meta/recipes-graphics/wayland/libinput_1.30.4.bb
@@ -13,11 +13,9 @@  LIC_FILES_CHKSUM = "file://COPYING;md5=bab4ac7dc1c10bc0fb037dc76c46ef8a"
 DEPENDS = "libevdev udev"
 
 SRC_URI = "git://gitlab.freedesktop.org/libinput/libinput.git;protocol=https;branch=1.30-branch;tag=${PV} \
-           file://CVE-2026-35093.patch \
-           file://CVE-2026-35094.patch \
            file://run-ptest \
            "
-SRCREV = "042c5e6fd9cc910307027a1522453794b29f2c72"
+SRCREV = "7ad8b37ffcc71aceb8eb4d079d22490e87168f49"
 
 UPSTREAM_CHECK_GITTAGREGEX = "(?P<pver>\d+\.\d+\.(?!9\d+)\d+)"