udisks-2.11.0-udiskslinuxmanager_use_after_free.patch 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. From 3dc036fb5045fc068c6abfbe4e62d0871d7ca82a Mon Sep 17 00:00:00 2001
  2. From: xinpeng wang <wangxinpeng@uniontech.com>
  3. Date: Thu, 21 Sep 2023 13:57:40 +0800
  4. Subject: [PATCH] udiskslinuxmanager:use dbus interface after free
  5. In handle_get_block_devices, call get_block_objects to obtain iface_block_device
  6. of all current UDisksLinuxBlockObject, and then obtain the corresponding
  7. UDisksLinuxBlockObject's object_path through iface_block_device.iface_block_device
  8. is a GDBusInterfaceSkeleton, which saves the object through
  9. g_dbus_interface_skeleton_set_object. g_object_add_weak_pointer is used here. This
  10. function is not thread-safe.At this time, if other threads are releasing the object,
  11. the program will crash.
  12. This scene can be reproduced by quickly plugging and unplugging the USB disk.
  13. The core is as follows (the redundant stack is omitted):
  14. When accessing object in thread 1, the object is released by thread 2
  15. info threads
  16. Id Target Id Frame
  17. * 1 Thread 0x7f80979e70 (LWP 24559) 0x0000007f8a48dda0 in
  18. g_dbus_object_get_object_path (object=0x0) at ../../../gio/gdbusobject.c:109
  19. 2 Thread 0x7f88a43010 (LWP 1159) 0x0000007f8a0a6ae8 in __GI___libc_free
  20. (mem=0x556a919c80) at malloc.c:3093
  21. thread 1
  22. (gdb) bt
  23. 0 0x0000007f8a48dda0 in g_dbus_object_get_object_path (object=0x0) at
  24. ../../../gio/gdbusobject.c:109
  25. 1 0x000000556a56911c in handle_get_block_devices (object=0x7f7c007ed0, invocation=
  26. 0x7f74016f20 [GDBusMethodInvocation], arg_options=<optimized out>)
  27. at udiskslinuxmanager.c:1063
  28. (gdb) p ((GObject*)(blocks_p->data))->ref_count
  29. $3 = 1
  30. (gdb) p *((GDBusInterfaceSkeleton*)(blocks_p->data))
  31. $6 = {parent_instance = {g_type_instance = {g_class = 0x556a64e740
  32. [g_type: UDisksLinuxBlock/UDisksBlockSkeleton/GDBusInterfaceSkeleton]}, ref_count = 1,
  33. qdata = 0x0}, priv = 0x7f7c004ac0}
  34. (gdb) p *((GDBusInterfaceSkeleton*)(blocks_p->data))->priv
  35. $7 = {lock = {p = 0x0, i = {0, 0}}, object = 0x0,
  36. flags = G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD,
  37. connections = 0x0, object_path = 0x0, hooked_vtable = 0x556a62b9f0}
  38. thread 2
  39. (gdb) bt
  40. 0 0x0000007f8a0a6ae8 in __GI___libc_free (mem=0x556a919c80) at malloc.c:3093
  41. 1 0x0000007f89ff1224 in () at /lib/aarch64-linux-gnu/libudev.so.1
  42. 2 0x0000007f89ff1348 in () at /lib/aarch64-linux-gnu/libudev.so.1
  43. 3 0x0000007f89ff5520 in () at /lib/aarch64-linux-gnu/libudev.so.1
  44. 4 0x0000007f89fff878 in udev_device_unref () at /lib/aarch64-linux-gnu/libudev.so.1
  45. 5 0x0000007f8a7aeb74 in () at /lib/aarch64-linux-gnu/libgudev-1.0.so.0
  46. 6 0x0000007f8a3193f8 in g_object_unref (_object=<optimized out>) at
  47. ../../../gobject/gobject.c:3346
  48. 7 0x0000007f8a3193f8 in g_object_unref (_object=0x7f680038a0) at
  49. ../../../gobject/gobject.c:3238
  50. 8 0x000000556a57700c in udisks_linux_device_finalize (object=0x7f5c005730
  51. [UDisksLinuxDevice]) at udiskslinuxdevice.c:75
  52. 9 0x0000007f8a3193f8 in g_object_unref (_object=<optimized out>) at
  53. ../../../gobject/gobject.c:3346
  54. 10 0x0000007f8a3193f8 in g_object_unref (_object=0x7f5c005730) at
  55. ../../../gobject/gobject.c:3238
  56. 11 0x000000556a55d0fc in udisks_linux_drive_object_uevent
  57. (object=object@entry=0x556a5df370 [UDisksLinuxDriveObject],
  58. action=action@entry=0x556a87b120
  59. "remove",device=device@entry=0x7f74007610 [UDisksLinuxDevice])
  60. at udiskslinuxdriveobject.c:715
  61. 12 0x000000556a54840c in handle_block_uevent_for_drive
  62. (provider=provider@entry=0x556a5c8200 [UDisksLinuxProvider],
  63. action=action@entry=0x556a87b120 "remove",device=device@entry=0x7f74007610
  64. [UDisksLinuxDevice]) at udiskslinuxprovider.c:1035
  65. 13 0x000000556a548ab8 in handle_block_uevent (device=0x7f74007610 [UDisksLinuxDevice],
  66. action=0x556a87b120 "remove", provider=0x556a5c8200 [UDisksLinuxProvider]) at
  67. udiskslinuxprovider.c:1349
  68. 14 0x000000556a548ab8 in udisks_linux_provider_handle_uevent
  69. (provider=0x556a5c8200 [UDisksLinuxProvider], action=0x556a87b120 "remove",
  70. device=0x7f74007610 [UDisksLinuxDevice]) at udiskslinuxprovider.c:1399
  71. 15 0x000000556a548cac in on_idle_with_probed_uevent (user_data=0x556a7e65a0) at
  72. udiskslinuxprovider.c:230
  73. ---
  74. src/udiskslinuxmanager.c | 13 +++++++++----
  75. 1 file changed, 9 insertions(+), 4 deletions(-)
  76. diff --git a/src/udiskslinuxmanager.c b/src/udiskslinuxmanager.c
  77. index 5bfeec103..491edb92b 100644
  78. --- a/src/udiskslinuxmanager.c
  79. +++ b/src/udiskslinuxmanager.c
  80. @@ -1196,8 +1196,11 @@ handle_get_block_devices (UDisksManager *object,
  81. blocks = get_block_objects (object, &num_blocks);
  82. block_paths = g_new0 (const gchar *, num_blocks + 1);
  83. - for (i = 0,blocks_p = blocks; blocks_p != NULL; blocks_p = blocks_p->next, i++)
  84. - block_paths[i] = g_dbus_object_get_object_path (g_dbus_interface_get_object (G_DBUS_INTERFACE (blocks_p->data)));
  85. + for (blocks_p = blocks; blocks_p != NULL; blocks_p = blocks_p->next) {
  86. + GDBusObject * block_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (blocks_p->data));
  87. + if (block_object)
  88. + block_paths[i++] = g_dbus_object_get_object_path (block_object);
  89. + }
  90. udisks_manager_complete_get_block_devices (object,
  91. invocation,
  92. @@ -1284,9 +1287,11 @@ handle_resolve_device (UDisksManager *object,
  93. }
  94. ret_paths = g_new0 (const gchar *, num_found + 1);
  95. - for (i = 0,ret_p = ret; ret_p != NULL; ret_p = ret_p->next, i++)
  96. + for (i = 0,ret_p = ret; ret_p != NULL; ret_p = ret_p->next)
  97. {
  98. - ret_paths[i] = g_dbus_object_get_object_path (g_dbus_interface_get_object (G_DBUS_INTERFACE (ret_p->data)));
  99. + GDBusObject *block_object = g_dbus_interface_get_object (G_DBUS_INTERFACE (ret_p->data));
  100. + if (block_object)
  101. + ret_paths[i++] = g_dbus_object_get_object_path (block_object);
  102. }
  103. udisks_manager_complete_resolve_device (object,