From 3aab25856ff1ebe16c248e1a698502e85304ef05 Mon Sep 17 00:00:00 2001 From: cenhuilin Date: Tue, 18 Jun 2024 16:39:21 +0800 Subject: [PATCH] udiskslinuxmanager:use dbus interface after free (cherry picked from commit 33f421a7f360d5ab58800b99fcd02f9d71d116de) --- ...anager-use-dbus-interface-after-free.patch | 115 ++++++++++++++++++ udisks2.spec | 6 +- 2 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 0002-udiskslinuxmanager-use-dbus-interface-after-free.patch diff --git a/0002-udiskslinuxmanager-use-dbus-interface-after-free.patch b/0002-udiskslinuxmanager-use-dbus-interface-after-free.patch new file mode 100644 index 0000000..32dabbe --- /dev/null +++ b/0002-udiskslinuxmanager-use-dbus-interface-after-free.patch @@ -0,0 +1,115 @@ +From 3dc036fb5045fc068c6abfbe4e62d0871d7ca82a Mon Sep 17 00:00:00 2001 +From: xinpeng wang +Date: Tue, 18 Jun 2024 16:32:39 +0800 +Subject: [PATCH] udiskslinuxmanager:use dbus interface after free + +In handle_get_block_devices, call get_block_objects to obtain iface_block_device +of all current UDisksLinuxBlockObject, and then obtain the corresponding +UDisksLinuxBlockObject's object_path through iface_block_device.iface_block_device +is a GDBusInterfaceSkeleton, which saves the object through +g_dbus_interface_skeleton_set_object. g_object_add_weak_pointer is used here. This +function is not thread-safe.At this time, if other threads are releasing the object, +the program will crash. +This scene can be reproduced by quickly plugging and unplugging the USB disk. +The core is as follows (the redundant stack is omitted): +When accessing object in thread 1, the object is released by thread 2 +info threads + Id Target Id Frame +* 1 Thread 0x7f80979e70 (LWP 24559) 0x0000007f8a48dda0 in +g_dbus_object_get_object_path (object=0x0) at ../../../gio/gdbusobject.c:109 + 2 Thread 0x7f88a43010 (LWP 1159) 0x0000007f8a0a6ae8 in __GI___libc_free +(mem=0x556a919c80) at malloc.c:3093 + +thread 1 +(gdb) bt +0 0x0000007f8a48dda0 in g_dbus_object_get_object_path (object=0x0) at +../../../gio/gdbusobject.c:109 +1 0x000000556a56911c in handle_get_block_devices (object=0x7f7c007ed0, invocation= +0x7f74016f20 [GDBusMethodInvocation], arg_options=) + at udiskslinuxmanager.c:1063 + +(gdb) p ((GObject*)(blocks_p->data))->ref_count +$3 = 1 +(gdb) p *((GDBusInterfaceSkeleton*)(blocks_p->data)) +$6 = {parent_instance = {g_type_instance = {g_class = 0x556a64e740 +[g_type: UDisksLinuxBlock/UDisksBlockSkeleton/GDBusInterfaceSkeleton]}, ref_count = 1, +qdata = 0x0}, priv = 0x7f7c004ac0} +(gdb) p *((GDBusInterfaceSkeleton*)(blocks_p->data))->priv +$7 = {lock = {p = 0x0, i = {0, 0}}, object = 0x0, +flags = G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD, +connections = 0x0, object_path = 0x0, hooked_vtable = 0x556a62b9f0} + +thread 2 +(gdb) bt +0 0x0000007f8a0a6ae8 in __GI___libc_free (mem=0x556a919c80) at malloc.c:3093 +1 0x0000007f89ff1224 in () at /lib/aarch64-linux-gnu/libudev.so.1 +2 0x0000007f89ff1348 in () at /lib/aarch64-linux-gnu/libudev.so.1 +3 0x0000007f89ff5520 in () at /lib/aarch64-linux-gnu/libudev.so.1 +4 0x0000007f89fff878 in udev_device_unref () at /lib/aarch64-linux-gnu/libudev.so.1 +5 0x0000007f8a7aeb74 in () at /lib/aarch64-linux-gnu/libgudev-1.0.so.0 +6 0x0000007f8a3193f8 in g_object_unref (_object=) at +../../../gobject/gobject.c:3346 +7 0x0000007f8a3193f8 in g_object_unref (_object=0x7f680038a0) at +../../../gobject/gobject.c:3238 +8 0x000000556a57700c in udisks_linux_device_finalize (object=0x7f5c005730 +[UDisksLinuxDevice]) at udiskslinuxdevice.c:75 +9 0x0000007f8a3193f8 in g_object_unref (_object=) at +../../../gobject/gobject.c:3346 +10 0x0000007f8a3193f8 in g_object_unref (_object=0x7f5c005730) at +../../../gobject/gobject.c:3238 +11 0x000000556a55d0fc in udisks_linux_drive_object_uevent + (object=object@entry=0x556a5df370 [UDisksLinuxDriveObject], +action=action@entry=0x556a87b120 +"remove",device=device@entry=0x7f74007610 [UDisksLinuxDevice]) + at udiskslinuxdriveobject.c:715 +12 0x000000556a54840c in handle_block_uevent_for_drive + (provider=provider@entry=0x556a5c8200 [UDisksLinuxProvider], +action=action@entry=0x556a87b120 "remove",device=device@entry=0x7f74007610 +[UDisksLinuxDevice]) at udiskslinuxprovider.c:1035 +13 0x000000556a548ab8 in handle_block_uevent (device=0x7f74007610 [UDisksLinuxDevice], +action=0x556a87b120 "remove", provider=0x556a5c8200 [UDisksLinuxProvider]) at +udiskslinuxprovider.c:1349 +14 0x000000556a548ab8 in udisks_linux_provider_handle_uevent + (provider=0x556a5c8200 [UDisksLinuxProvider], action=0x556a87b120 "remove", +device=0x7f74007610 [UDisksLinuxDevice]) at udiskslinuxprovider.c:1399 +15 0x000000556a548cac in on_idle_with_probed_uevent (user_data=0x556a7e65a0) at +udiskslinuxprovider.c:230 +--- + src/udiskslinuxmanager.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/src/udiskslinuxmanager.c b/src/udiskslinuxmanager.c +index 5bfeec1..491edb9 100644 +--- a/src/udiskslinuxmanager.c ++++ b/src/udiskslinuxmanager.c +@@ -1196,8 +1196,11 @@ handle_get_block_devices (UDisksManager *object, + blocks = get_block_objects (object, &num_blocks); + block_paths = g_new0 (const gchar *, num_blocks + 1); + +- for (i = 0,blocks_p = blocks; blocks_p != NULL; blocks_p = blocks_p->next, i++) +- block_paths[i] = g_dbus_object_get_object_path (g_dbus_interface_get_object (G_DBUS_INTERFACE (blocks_p->data))); ++ for (blocks_p = blocks; blocks_p != NULL; blocks_p = blocks_p->next) { ++ GDBusObject * block_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (blocks_p->data)); ++ if (block_object) ++ block_paths[i++] = g_dbus_object_get_object_path (block_object); ++ } + + udisks_manager_complete_get_block_devices (object, + invocation, +@@ -1284,9 +1287,11 @@ handle_resolve_device (UDisksManager *object, + } + + ret_paths = g_new0 (const gchar *, num_found + 1); +- for (i = 0,ret_p = ret; ret_p != NULL; ret_p = ret_p->next, i++) ++ for (i = 0,ret_p = ret; ret_p != NULL; ret_p = ret_p->next) + { +- ret_paths[i] = g_dbus_object_get_object_path (g_dbus_interface_get_object (G_DBUS_INTERFACE (ret_p->data))); ++ GDBusObject *block_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (ret_p->data)); ++ if (block_object) ++ ret_paths[i++] = g_dbus_object_get_object_path (block_object); + } + + udisks_manager_complete_resolve_device (object, +-- +2.33.0 + diff --git a/udisks2.spec b/udisks2.spec index a9e1d81..798c009 100644 --- a/udisks2.spec +++ b/udisks2.spec @@ -19,13 +19,14 @@ Name: udisks2 Summary: Disk Manager Version: 2.10.1 -Release: 2 +Release: 3 License: GPL-2.0+ and LGPL-2.0+ Group: System Environment/Libraries URL: https://github.com/storaged-project/udisks Source0: https://github.com/storaged-project/udisks/releases/download/udisks-%{version}/udisks-%{version}.tar.bz2 Patch0001: 0001-mdraid-Expose-consistency_policy-sysfs-value.patch +Patch0002: 0002-udiskslinuxmanager-use-dbus-interface-after-free.patch BuildRequires: make BuildRequires: glib2-devel >= %{glib2_version} @@ -316,6 +317,9 @@ fi %changelog +* Tue Jun 18 2024 cenhuilin - 2.10.1-3 +- udiskslinuxmanager:use dbus interface after free + * Wed Jun 12 2024 Deyuan Fan - 2.10.1-2 - mdraid: Expose "consistency_policy" sysfs value -- Gitee