From patchwork Tue Apr 14 16:15:29 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Burton X-Patchwork-Id: 86024 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 45126F9D0E4 for ; Tue, 14 Apr 2026 16:15:38 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.551.1776183333033288126 for ; Tue, 14 Apr 2026 09:15:33 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@arm.com header.s=foss header.b=GPCWyJZN; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: ross.burton@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E7707445E for ; Tue, 14 Apr 2026 09:15:26 -0700 (PDT) Received: from cesw-amp-gbt-1s-m12830-04.lab.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 360143F641 for ; Tue, 14 Apr 2026 09:15:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1776183332; bh=GyfpuIxfUxaIjAd0zqvpBcTMvnl3iHr8VNPh2O5viJc=; h=From:To:Subject:Date:From; b=GPCWyJZNRn7+f3aLpN23cW+DjAZKBkdA4AR271Ovf1+mzjojhs6LMyzvVDVjxcDtv M6x5jINLDZV7Efiz+4cnmMKhvosbN2l5aQWCipXdbwSusbGoYVk+7wma0g/fheX7vk W2E0UOnXIU04iTgNipgba8WlJb8MqSsgy8cwgY0I= From: Ross Burton To: openembedded-core@lists.openembedded.org Subject: [PATCH 1/2] libinput: backport fixes for CVE-2026-35093 and CVE-2026-35094 Date: Tue, 14 Apr 2026 17:15:29 +0100 Message-ID: <20260414161530.1279308-1-ross.burton@arm.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 14 Apr 2026 16:15:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/235168 Backport the patches from upstream for these CVEs in the Lua plugin. Signed-off-by: Ross Burton --- .../wayland/libinput/CVE-2026-35093.patch | 124 ++++++++++++ .../wayland/libinput/CVE-2026-35094.patch | 191 ++++++++++++++++++ .../wayland/libinput_1.30.2.bb | 2 + 3 files changed, 317 insertions(+) create mode 100644 meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch create mode 100644 meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch diff --git a/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch b/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch new file mode 100644 index 00000000000..e0119caaca1 --- /dev/null +++ b/meta/recipes-graphics/wayland/libinput/CVE-2026-35093.patch @@ -0,0 +1,124 @@ +From 356c498fd4ba25ec99f6866fc96847ec3d1f16bf Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +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 +Part-of: + +CVE: CVE-2025-35093 +Upstream-Status: Backport +Signed-off-by: Ross Burton +--- + 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 new file mode 100644 index 00000000000..405a262b03e --- /dev/null +++ b/meta/recipes-graphics/wayland/libinput/CVE-2026-35094.patch @@ -0,0 +1,191 @@ +From 45dfd0f0301af855f068df27b2e40cc9f5713acd Mon Sep 17 00:00:00 2001 +From: Peter Hutterer +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 +Part-of: + +CVE: CVE-2025-35094 +Upstream-Status: Backport +Signed-off-by: Ross Burton + +--- + 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.2.bb index 5d9bfafaaa3..efd51809d8e 100644 --- a/meta/recipes-graphics/wayland/libinput_1.30.2.bb +++ b/meta/recipes-graphics/wayland/libinput_1.30.2.bb @@ -13,6 +13,8 @@ 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" From patchwork Tue Apr 14 16:15:30 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ross Burton X-Patchwork-Id: 86023 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 53CCBF9D0E2 for ; Tue, 14 Apr 2026 16:15:38 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by mx.groups.io with SMTP id smtpd.msgproc01-g2.563.1776183333699194472 for ; Tue, 14 Apr 2026 09:15:33 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@arm.com header.s=foss header.b=plDWisfD; spf=pass (domain: arm.com, ip: 217.140.110.172, mailfrom: ross.burton@arm.com) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 9600A445E for ; Tue, 14 Apr 2026 09:15:27 -0700 (PDT) Received: from cesw-amp-gbt-1s-m12830-04.lab.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.121.207.14]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id DC03D3F641 for ; Tue, 14 Apr 2026 09:15:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=arm.com; s=foss; t=1776183333; bh=aKpq9Ad9CE5I3u3tUMzLsEqoJL0PIfooLILrQjyDETQ=; h=From:To:Subject:Date:In-Reply-To:References:From; b=plDWisfDHiU2Gl34pBX/GdNWNdsvZptguCgmSzxrGWlNfLMsH3/5zQWGKuAQlbIZD rEyBKk++BmYJIkdOQUDVbCwOrtdDGCOIagydMQirbcODH8i/hIT/+dWRkPZUtVJHKE 5qzsJ20h+a1mmfdbUO9yFCRl9Ko7NEuuzZp6jRgY= From: Ross Burton To: openembedded-core@lists.openembedded.org Subject: [PATCH 2/2] glib-networking: backport fixes for CVE-2025-60018 and CVE-2025-60019 Date: Tue, 14 Apr 2026 17:15:30 +0100 Message-ID: <20260414161530.1279308-2-ross.burton@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260414161530.1279308-1-ross.burton@arm.com> References: <20260414161530.1279308-1-ross.burton@arm.com> MIME-Version: 1.0 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Tue, 14 Apr 2026 16:15:38 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/235169 CVE-2025-60018: glib-networking's OpenSSL backend fails to properly check the return value of a call to BIO_write(), resulting in an out of bounds read. CVE-2205-60019: glib-networking's OpenSSL backend fails to properly check the return value of memory allocation routines. An out of memory condition could potentially result in writing to an invalid memory location. Signed-off-by: Ross Burton --- ...-check-return-value-when-writing-to-.patch | 82 ++++++++++ ...heck-return-value-of-g_tls_bio_alloc.patch | 42 +++++ ...enssl-check-return-values-of-BIO_new.patch | 146 ++++++++++++++++++ .../glib-networking/glib-networking_2.80.1.bb | 5 +- 4 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 meta/recipes-core/glib-networking/glib-networking/0001-openssl-properly-check-return-value-when-writing-to-.patch create mode 100644 meta/recipes-core/glib-networking/glib-networking/0002-openssl-check-return-value-of-g_tls_bio_alloc.patch create mode 100644 meta/recipes-core/glib-networking/glib-networking/0003-openssl-check-return-values-of-BIO_new.patch diff --git a/meta/recipes-core/glib-networking/glib-networking/0001-openssl-properly-check-return-value-when-writing-to-.patch b/meta/recipes-core/glib-networking/glib-networking/0001-openssl-properly-check-return-value-when-writing-to-.patch new file mode 100644 index 00000000000..72f0c0c61ef --- /dev/null +++ b/meta/recipes-core/glib-networking/glib-networking/0001-openssl-properly-check-return-value-when-writing-to-.patch @@ -0,0 +1,82 @@ +From 330f59dcb39386b3d640ce94fcd3f75e1668ad88 Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Mon, 4 Aug 2025 15:10:21 -0500 +Subject: [PATCH 1/3] openssl: properly check return value when writing to BIO + objects + +In particular, we will read out of bounds, and then write the invalid +memory, if BIO_write() fails when getting the PROP_CERTIFICATE_PEM +property. Here we attempt to check the return value, but the check is +not correct. + +This also fixes a leak of the BIO in the same place. + +Also add error checking to PROP_SUBJECT_NAME and PROP_ISSUER_NAME, for +good measure. + +Fixes #226 + +CVE: CVE-2025-60018 +Upstream-Status: Backport +Signed-off-by: Ross Burton +--- + tls/openssl/gtlscertificate-openssl.c | 25 +++++++++++++++---------- + 1 file changed, 15 insertions(+), 10 deletions(-) + +diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c +index 648f3e8..b536559 100644 +--- a/tls/openssl/gtlscertificate-openssl.c ++++ b/tls/openssl/gtlscertificate-openssl.c +@@ -362,15 +362,12 @@ g_tls_certificate_openssl_get_property (GObject *object, + case PROP_CERTIFICATE_PEM: + bio = BIO_new (BIO_s_mem ()); + +- if (!PEM_write_bio_X509 (bio, openssl->cert) || !BIO_write (bio, "\0", 1)) +- certificate_pem = NULL; +- else ++ if (PEM_write_bio_X509 (bio, openssl->cert) == 1 && BIO_write (bio, "\0", 1) == 1) + { + BIO_get_mem_data (bio, &certificate_pem); + g_value_set_string (value, certificate_pem); +- +- BIO_free_all (bio); + } ++ BIO_free_all (bio); + break; + + case PROP_PRIVATE_KEY: +@@ -411,8 +408,12 @@ g_tls_certificate_openssl_get_property (GObject *object, + case PROP_SUBJECT_NAME: + bio = BIO_new (BIO_s_mem ()); + name = X509_get_subject_name (openssl->cert); +- X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS); +- BIO_write (bio, "\0", 1); ++ if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 || ++ BIO_write (bio, "\0", 1) != 1) ++ { ++ BIO_free_all (bio); ++ break; ++ } + BIO_get_mem_data (bio, (char **)&name_string); + g_value_set_string (value, name_string); + BIO_free_all (bio); +@@ -421,9 +422,13 @@ g_tls_certificate_openssl_get_property (GObject *object, + case PROP_ISSUER_NAME: + bio = BIO_new (BIO_s_mem ()); + name = X509_get_issuer_name (openssl->cert); +- X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS); +- BIO_write (bio, "\0", 1); +- BIO_get_mem_data (bio, &name_string); ++ if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 || ++ BIO_write (bio, "\0", 1) != 1) ++ { ++ BIO_free_all (bio); ++ break; ++ } ++ BIO_get_mem_data (bio, (char **)&name_string); + g_value_set_string (value, name_string); + BIO_free_all (bio); + break; +-- +2.43.0 + diff --git a/meta/recipes-core/glib-networking/glib-networking/0002-openssl-check-return-value-of-g_tls_bio_alloc.patch b/meta/recipes-core/glib-networking/glib-networking/0002-openssl-check-return-value-of-g_tls_bio_alloc.patch new file mode 100644 index 00000000000..9c3d19f373d --- /dev/null +++ b/meta/recipes-core/glib-networking/glib-networking/0002-openssl-check-return-value-of-g_tls_bio_alloc.patch @@ -0,0 +1,42 @@ +From b5a3a8b28b7616403d5454f5f1816c933c34cdac Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 21 Aug 2025 16:58:54 -0500 +Subject: [PATCH 2/3] openssl: check return value of g_tls_bio_alloc() + +This function may fail, in which case the parameter remains +uninitialized. We'd better not dereference it in that case. + +CVE: CVE-2025-60019 +Upstream-Status: Backport +Signed-off-by: Ross Burton +--- + tls/openssl/gtlsbio.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/tls/openssl/gtlsbio.c b/tls/openssl/gtlsbio.c +index 0f603fe..1e54943 100644 +--- a/tls/openssl/gtlsbio.c ++++ b/tls/openssl/gtlsbio.c +@@ -370,7 +370,8 @@ g_tls_bio_new_from_iostream (GIOStream *io_stream) + GTlsBio *gbio; + + ret = g_tls_bio_alloc (&gbio); +- gbio->io_stream = g_object_ref (io_stream); ++ if (ret) ++ gbio->io_stream = g_object_ref (io_stream); + + return ret; + } +@@ -382,7 +383,8 @@ g_tls_bio_new_from_datagram_based (GDatagramBased *socket) + GTlsBio *gbio; + + ret = g_tls_bio_alloc (&gbio); +- gbio->socket = g_object_ref (socket); ++ if (ret) ++ gbio->socket = g_object_ref (socket); + + return ret; + } +-- +2.43.0 + diff --git a/meta/recipes-core/glib-networking/glib-networking/0003-openssl-check-return-values-of-BIO_new.patch b/meta/recipes-core/glib-networking/glib-networking/0003-openssl-check-return-values-of-BIO_new.patch new file mode 100644 index 00000000000..1e925da980c --- /dev/null +++ b/meta/recipes-core/glib-networking/glib-networking/0003-openssl-check-return-values-of-BIO_new.patch @@ -0,0 +1,146 @@ +From 9c22e08b41255543bc15017123ed6c64b97b9b7c Mon Sep 17 00:00:00 2001 +From: Michael Catanzaro +Date: Thu, 21 Aug 2025 17:21:01 -0500 +Subject: [PATCH 3/3] openssl: check return values of BIO_new() + +We probably need to check even more return values of even more OpenSSL +functions, but these ones allocate memory and that's particularly +important to get right. + +CVE: CVE-2025-60019 +Upstream-Status: Backport +Signed-off-by: Ross Burton +--- + tls/openssl/gtlscertificate-openssl.c | 42 ++++++++++++++++++++------- + 1 file changed, 32 insertions(+), 10 deletions(-) + +diff --git a/tls/openssl/gtlscertificate-openssl.c b/tls/openssl/gtlscertificate-openssl.c +index b536559..4fa5286 100644 +--- a/tls/openssl/gtlscertificate-openssl.c ++++ b/tls/openssl/gtlscertificate-openssl.c +@@ -166,6 +166,9 @@ export_privkey_to_der (GTlsCertificateOpenssl *openssl, + goto err; + + bio = BIO_new (BIO_s_mem ()); ++ if (!bio) ++ goto err; ++ + if (i2d_PKCS8_PRIV_KEY_INFO_bio (bio, pkcs8) == 0) + goto err; + +@@ -199,6 +202,9 @@ export_privkey_to_pem (GTlsCertificateOpenssl *openssl) + return NULL; + + bio = BIO_new (BIO_s_mem ()); ++ if (!bio) ++ goto out; ++ + ret = PEM_write_bio_PKCS8PrivateKey (bio, openssl->key, NULL, NULL, 0, NULL, NULL); + if (ret == 0) + goto out; +@@ -211,7 +217,7 @@ export_privkey_to_pem (GTlsCertificateOpenssl *openssl) + result = g_strdup (data); + + out: +- BIO_free_all (bio); ++ g_clear_pointer (&bio, BIO_free_all); + return result; + } + +@@ -232,6 +238,9 @@ maybe_import_pkcs12 (GTlsCertificateOpenssl *openssl) + return; + + bio = BIO_new (BIO_s_mem ()); ++ if (!bio) ++ goto import_failed; ++ + status = BIO_write (bio, openssl->pkcs12_data->data, openssl->pkcs12_data->len); + if (status <= 0) + goto import_failed; +@@ -323,7 +332,7 @@ g_tls_certificate_openssl_get_property (GObject *object, + guint8 *data; + BIO *bio; + GByteArray *byte_array; +- char *certificate_pem; ++ const char *certificate_pem; + long size; + + const ASN1_TIME *time_asn1; +@@ -362,12 +371,12 @@ g_tls_certificate_openssl_get_property (GObject *object, + case PROP_CERTIFICATE_PEM: + bio = BIO_new (BIO_s_mem ()); + +- if (PEM_write_bio_X509 (bio, openssl->cert) == 1 && BIO_write (bio, "\0", 1) == 1) ++ if (bio && PEM_write_bio_X509 (bio, openssl->cert) == 1 && BIO_write (bio, "\0", 1) == 1) + { + BIO_get_mem_data (bio, &certificate_pem); + g_value_set_string (value, certificate_pem); + } +- BIO_free_all (bio); ++ g_clear_pointer (&bio, BIO_free_all); + break; + + case PROP_PRIVATE_KEY: +@@ -407,6 +416,8 @@ g_tls_certificate_openssl_get_property (GObject *object, + + case PROP_SUBJECT_NAME: + bio = BIO_new (BIO_s_mem ()); ++ if (!bio) ++ break; + name = X509_get_subject_name (openssl->cert); + if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 || + BIO_write (bio, "\0", 1) != 1) +@@ -421,6 +432,8 @@ g_tls_certificate_openssl_get_property (GObject *object, + + case PROP_ISSUER_NAME: + bio = BIO_new (BIO_s_mem ()); ++ if (!bio) ++ break; + name = X509_get_issuer_name (openssl->cert); + if (X509_NAME_print_ex (bio, name, 0, XN_FLAG_SEP_COMMA_PLUS) < 0 || + BIO_write (bio, "\0", 1) != 1) +@@ -533,8 +546,11 @@ g_tls_certificate_openssl_set_property (GObject *object, + break; + CRITICAL_IF_CERTIFICATE_INITIALIZED ("certificate-pem"); + bio = BIO_new_mem_buf ((gpointer)string, -1); +- openssl->cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL); +- BIO_free (bio); ++ if (bio) ++ { ++ openssl->cert = PEM_read_bio_X509 (bio, NULL, NULL, NULL); ++ BIO_free (bio); ++ } + if (openssl->cert) + openssl->have_cert = TRUE; + else if (!openssl->construct_error) +@@ -554,8 +570,11 @@ g_tls_certificate_openssl_set_property (GObject *object, + CRITICAL_IF_KEY_INITIALIZED ("private-key"); + + bio = BIO_new_mem_buf (bytes->data, bytes->len); +- openssl->key = d2i_PrivateKey_bio (bio, NULL); +- BIO_free (bio); ++ if (bio) ++ { ++ openssl->key = d2i_PrivateKey_bio (bio, NULL); ++ BIO_free (bio); ++ } + if (openssl->key) + openssl->have_key = TRUE; + else if (!openssl->construct_error) +@@ -575,8 +594,11 @@ g_tls_certificate_openssl_set_property (GObject *object, + CRITICAL_IF_KEY_INITIALIZED ("private-key-pem"); + + bio = BIO_new_mem_buf ((gpointer)string, -1); +- openssl->key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL); +- BIO_free (bio); ++ if (bio) ++ { ++ openssl->key = PEM_read_bio_PrivateKey (bio, NULL, NULL, NULL); ++ BIO_free (bio); ++ } + if (openssl->key) + openssl->have_key = TRUE; + else if (!openssl->construct_error) +-- +2.43.0 + diff --git a/meta/recipes-core/glib-networking/glib-networking_2.80.1.bb b/meta/recipes-core/glib-networking/glib-networking_2.80.1.bb index 8bdbab03a6a..44e3b0c0b3d 100644 --- a/meta/recipes-core/glib-networking/glib-networking_2.80.1.bb +++ b/meta/recipes-core/glib-networking/glib-networking_2.80.1.bb @@ -29,7 +29,10 @@ PACKAGECONFIG[gnomeproxy] = "-Dgnome_proxy=enabled,-Dgnome_proxy=disabled,gsetti inherit gnomebase gettext upstream-version-is-even gio-module-cache ptest-gnome -SRC_URI += "file://run-ptest" +SRC_URI += "file://0001-openssl-properly-check-return-value-when-writing-to-.patch \ + file://0002-openssl-check-return-value-of-g_tls_bio_alloc.patch \ + file://0003-openssl-check-return-values-of-BIO_new.patch \ + file://run-ptest" FILES:${PN} += "\ ${libdir}/gio/modules/libgio*.so \