From 0a8e738d62fc99466b39f4f25d4c9e343fe8199c Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Wed, 27 Nov 2013 14:00:21 -0500 Subject: engine: reject junk signals Check incoming signals for non-sense before bubbling them up to higher layers. This will avoid dconf APIs feeding invalid key names to applications during change notifications in the case that we're fed invalid data over D-Bus. --- engine/dconf-engine.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) (limited to 'engine') diff --git a/engine/dconf-engine.c b/engine/dconf-engine.c index 5e1ee7e..50a461b 100644 --- a/engine/dconf-engine.c +++ b/engine/dconf-engine.c @@ -25,6 +25,7 @@ #include "dconf-engine.h" #include "../common/dconf-error.h" +#include "../common/dconf-paths.h" #include "../gvdb/gvdb-reader.h" #include #include @@ -1219,6 +1220,36 @@ dconf_engine_handle_dbus_signal (GBusType type, g_variant_get (body, "(&s^a&s&s)", &prefix, &changes, &tag); + /* Reject junk */ + if (changes[0] == NULL) + /* No changes? Do nothing. */ + goto junk; + + if (dconf_is_key (prefix, NULL)) + { + /* If the prefix is a key then the changes must be ['']. */ + if (changes[0][0] || changes[1]) + goto junk; + } + else if (dconf_is_dir (prefix, NULL)) + { + /* If the prefix is a dir then we can have changes within that + * dir, but they must be rel paths. + * + * ie: + * + * ('/a/', ['b', 'c/']) == ['/a/b', '/a/c/'] + */ + gint i; + + for (i = 0; changes[i]; i++) + if (!dconf_is_rel_path (changes[i], NULL)) + goto junk; + } + else + /* Not a key or a dir? */ + goto junk; + g_mutex_lock (&dconf_engine_global_lock); engines = g_slist_copy_deep (dconf_engine_global_list, (GCopyFunc) dconf_engine_ref, NULL); g_mutex_unlock (&dconf_engine_global_lock); @@ -1242,6 +1273,7 @@ dconf_engine_handle_dbus_signal (GBusType type, dconf_engine_unref (engine); } +junk: g_free (changes); } @@ -1256,6 +1288,10 @@ dconf_engine_handle_dbus_signal (GBusType type, g_variant_get (body, "(&s)", &path); + /* Rejecting junk here is relatively straightforward */ + if (!dconf_is_path (path, NULL)) + return; + g_mutex_lock (&dconf_engine_global_lock); engines = g_slist_copy_deep (dconf_engine_global_list, (GCopyFunc) dconf_engine_ref, NULL); g_mutex_unlock (&dconf_engine_global_lock); -- cgit v1.2.1