diff options
author | Kalev Lember <klember@redhat.com> | 2017-01-27 15:11:43 +0100 |
---|---|---|
committer | Kalev Lember <klember@redhat.com> | 2017-01-27 15:42:46 +0100 |
commit | a3c03baee4b9ea9cb6ad8c4f04ab54c7fdec0a05 (patch) | |
tree | 606d8e662e7be7277387c4c270893bb441211a67 | |
parent | 08d5ffc6d07bd5922b116f075382602fe0377f6d (diff) | |
download | appstream-glib-a3c03baee4b9ea9cb6ad8c4f04ab54c7fdec0a05.tar.gz |
store: Fix use after free with hash table keys
AsStore keeps a priv->hash_id hash table with app ID's as keys and a
GPtrArray with the actual apps matching the app ID as values. To optimize
memory use, the keys are all AsRefStrings. As all AsRefStrings are reference
counted, they may get freed when the last app with the matching ID gets
removed.
To handle that case, make sure the remove the GPtrArray holding the apps as
well when removing last app matching an ID.
This fixes the following use after free when starting gnome-software:
==6065== Invalid read of size 1
==6065== at 0x8E26650: __strcmp_sse2_unaligned (in /usr/lib64/libc-2.24.so)
==6065== by 0x8585678: g_str_equal (ghash.c:1846)
==6065== by 0x8584BDF: g_hash_table_lookup_node (ghash.c:396)
==6065== by 0x8584BDF: g_hash_table_lookup (ghash.c:1147)
==6065== by 0x4E789F2: as_store_add_app (as-store.c:1229)
==6065== by 0x4E797CA: as_store_from_root (as-store.c:1537)
==6065== by 0x4E7A71F: as_store_from_file_internal (as-store.c:1880)
==6065== by 0x4E7B7A9: as_store_load_app_info_file (as-store.c:2556)
==6065== by 0x4E7B9B8: as_store_load_app_info (as-store.c:2611)
==6065== by 0x4E7C352: as_store_search_app_info (as-store.c:2847)
==6065== by 0x4E7C598: as_store_search_per_system (as-store.c:2883)
==6065== by 0x4E7CF7F: as_store_load (as-store.c:3068)
==6065== by 0x1E512B7B: gs_plugin_setup (gs-plugin-appstream.c:255)
==6065== by 0x46A2C5: gs_plugin_loader_setup (gs-plugin-loader.c:3912)
==6065== by 0x46ECCE: gs_application_initialize_plugins (gs-application.c:228)
==6065== by 0x46ED99: gs_application_dbus_register (gs-application.c:249)
==6065== by 0x8007167: g_application_impl_attempt_primary (gapplicationimpl-dbus.c:406)
==6065== by 0x8007167: g_application_impl_register (gapplicationimpl-dbus.c:555)
==6065== by 0x8003F22: g_application_register (gapplication.c:2033)
==6065== by 0x47064D: gs_application_handle_local_options (gs-application.c:864)
==6065== by 0xEFCFC57: ffi_call_unix64 (unix64.S:76)
==6065== by 0xEFCF6B9: ffi_call (ffi64.c:525)
==6065== Address 0x259c1994 is 4 bytes inside a block of size 31 free'd
==6065== at 0x4C2ED4A: free (vg_replace_malloc.c:530)
==6065== by 0x859B6BD: g_free (gmem.c:189)
==6065== by 0x4E70A37: as_ref_string_unref_from_str (as-ref-string.c:48)
==6065== by 0x8583D22: g_hash_table_remove_node (ghash.c:455)
==6065== by 0x8584647: g_hash_table_remove_internal (ghash.c:1358)
==6065== by 0x4E70E09: as_ref_string_unref (as-ref-string.c:225)
==6065== by 0x4E510B4: as_app_finalize (as-app.c:473)
==6065== by 0x830E116: g_object_unref (gobject.c:3185)
==6065== by 0x8569E2D: g_ptr_array_remove_index (garray.c:1188)
==6065== by 0x856A230: g_ptr_array_remove (garray.c:1321)
==6065== by 0x4E77D49: as_store_remove_app (as-store.c:931)
==6065== by 0x4E789DB: as_store_add_app (as-store.c:1225)
==6065== by 0x4E797CA: as_store_from_root (as-store.c:1537)
==6065== by 0x4E7A71F: as_store_from_file_internal (as-store.c:1880)
==6065== by 0x4E7B7A9: as_store_load_app_info_file (as-store.c:2556)
==6065== by 0x4E7B9B8: as_store_load_app_info (as-store.c:2611)
==6065== by 0x4E7C352: as_store_search_app_info (as-store.c:2847)
==6065== by 0x4E7C598: as_store_search_per_system (as-store.c:2883)
==6065== by 0x4E7CF7F: as_store_load (as-store.c:3068)
==6065== by 0x1E512B7B: gs_plugin_setup (gs-plugin-appstream.c:255)
==6065== Block was alloc'd at
==6065== at 0x4C2DB9D: malloc (vg_replace_malloc.c:299)
==6065== by 0x859B5A8: g_malloc (gmem.c:94)
==6065== by 0x4E70ABF: as_ref_string_new_copy_with_length (as-ref-string.c:99)
==6065== by 0x4E6B908: as_node_reflow_text (as-node.c:516)
==6065== by 0x4E6BEF7: as_node_text_cb (as-node.c:707)
==6065== by 0x859A14D: g_markup_parse_context_parse (gmarkup.c:1514)
==6065== by 0x4E6C29C: as_node_from_xml (as-node.c:825)
==6065== by 0x4E5BAA8: as_app_parse_appdata_file (as-app.c:5665)
==6065== by 0x4E5BE6A: as_app_parse_file (as-app.c:5781)
==6065== by 0x4E7BEDB: as_store_load_installed (as-store.c:2743)
==6065== by 0x4E7C24B: as_store_search_installed (as-store.c:2825)
==6065== by 0x4E7C636: as_store_search_per_system (as-store.c:2890)
==6065== by 0x4E7CF7F: as_store_load (as-store.c:3068)
==6065== by 0x1E512B7B: gs_plugin_setup (gs-plugin-appstream.c:255)
==6065== by 0x46A2C5: gs_plugin_loader_setup (gs-plugin-loader.c:3912)
==6065== by 0x46ECCE: gs_application_initialize_plugins (gs-application.c:228)
==6065== by 0x46ED99: gs_application_dbus_register (gs-application.c:249)
==6065== by 0x8007167: g_application_impl_attempt_primary (gapplicationimpl-dbus.c:406)
==6065== by 0x8007167: g_application_impl_register (gapplicationimpl-dbus.c:555)
==6065== by 0x8003F22: g_application_register (gapplication.c:2033)
==6065== by 0x47064D: gs_application_handle_local_options (gs-application.c:864)
-rw-r--r-- | libappstream-glib/as-store.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/libappstream-glib/as-store.c b/libappstream-glib/as-store.c index cdaaef8..b203797 100644 --- a/libappstream-glib/as-store.c +++ b/libappstream-glib/as-store.c @@ -927,6 +927,11 @@ as_store_remove_app (AsStore *store, AsApp *app) if (apps != NULL) g_ptr_array_remove (apps, app); + /* remove the array as well if it was the last app as the AsRefString + * with the app ID may get freed now */ + if (apps->len == 0) + g_hash_table_remove (priv->hash_id, as_app_get_id (app)); + g_hash_table_remove (priv->hash_unique_id, as_app_get_unique_id (app)); g_ptr_array_remove (priv->array, app); g_hash_table_remove_all (priv->metadata_indexes); |