summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalev Lember <klember@redhat.com>2017-01-27 15:11:43 +0100
committerKalev Lember <klember@redhat.com>2017-01-27 15:42:46 +0100
commita3c03baee4b9ea9cb6ad8c4f04ab54c7fdec0a05 (patch)
tree606d8e662e7be7277387c4c270893bb441211a67
parent08d5ffc6d07bd5922b116f075382602fe0377f6d (diff)
downloadappstream-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.c5
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);