summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2010-06-30 11:51:40 -0700
committerDan Williams <dcbw@redhat.com>2010-06-30 11:55:27 -0700
commit2c12569ead882b791289ef6101e6f1672a871301 (patch)
tree7f025ea5cf9b0aee8d935abca4a04915ae8bca40
parentbc93e6963b91dfb54871e55a37676551777f6507 (diff)
libnm-glib: fix invalid memory access during property notification
If an NMObject listened to property change notifications from other NMObjects and then in response to that queued up other property changes of it's own, those would get added to the property change list that was being iterated through already. Each name in the change list is freed after being notified, but the change list itself is actually freed when all properties have been notified. So an object that queues up another change notification ends up in _nm_object_queue_notify() which iterates the change list where half of the data elements are already freed...
-rw-r--r--libnm-glib/nm-object.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/libnm-glib/nm-object.c b/libnm-glib/nm-object.c
index 7e9bc2fa0b..ebf709e8e4 100644
--- a/libnm-glib/nm-object.c
+++ b/libnm-glib/nm-object.c
@@ -47,7 +47,7 @@ typedef struct {
NMObject *parent;
GSList *notify_props;
- gulong notify_id;
+ guint32 notify_id;
gboolean disposed;
} NMObjectPrivate;
@@ -255,18 +255,23 @@ deferred_notify_cb (gpointer data)
{
NMObject *object = NM_OBJECT (data);
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE (object);
- GSList *iter;
+ GSList *props, *iter;
priv->notify_id = 0;
- priv->notify_props = g_slist_reverse (priv->notify_props);
- for (iter = priv->notify_props; iter; iter = g_slist_next (iter)) {
+ /* Clear priv->notify_props early so that an NMObject subclass that
+ * listens to property changes can queue up other property changes
+ * during the g_object_notify() call separately from the property
+ * list we're iterating.
+ */
+ props = g_slist_reverse (priv->notify_props);
+ priv->notify_props = NULL;
+
+ for (iter = props; iter; iter = g_slist_next (iter)) {
g_object_notify (G_OBJECT (object), (const char *) iter->data);
g_free (iter->data);
}
- g_slist_free (priv->notify_props);
- priv->notify_props = NULL;
-
+ g_slist_free (props);
return FALSE;
}