summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJiří Klimeš <jklimes@redhat.com>2013-11-21 13:40:04 +0100
committerJiří Klimeš <jklimes@redhat.com>2013-11-26 14:43:11 +0100
commit91a95dd9165023966b4377ad49cd8342eab5d776 (patch)
tree9f92a04ae604524d934f4526680f47207f906abe
parent593f1aadec7536944efe21a1e8941ced4746df86 (diff)
downloadNetworkManager-91a95dd9165023966b4377ad49cd8342eab5d776.tar.gz
agents: fix crash in nm_secret_agent_cancel_secrets() (rh #922855)
When request for getting secrets is being freed in request_free(), cancel_callback is get_cancel_cb(). It uses parent->current as a secret agent object. However, this object can be already freed and thus there is a problem getting priv in nm_secret_agent_cancel_secrets: g_return_if_fail (self != NULL); priv = NM_SECRET_AGENT_GET_PRIVATE (self); (gdb) p self $66 = (NMSecretAgent *) 0x7fae9afd42e0 (gdb) p *self $67 = {parent = {g_type_instance = {g_class = 0x0}, ref_count = 0, qdata = 0x0}} #0 nm_secret_agent_cancel_secrets (self=0x7fae9afd42e0, call=0x1) at settings/nm-secret-agent.c:325 #1 0x00007fae9a774882 in request_free (req=0x7fae9afc48f0) at settings/nm-agent-manager.c:496 #2 0x00007fae967b251a in g_hash_table_remove_internal (hash_table=0x7fae9aefdf00, key=0x2, notify=1) at ghash.c:1276 #3 0x00007fae9a72b340 in dispose (object=0x7fae9af77200) at nm-activation-request.c:446 #4 0x00007fae96cbeee8 in g_object_unref (_object=0x7fae9af77200) at gobject.c:3160 #5 0x00007fae9a73d87c in _active_connection_cleanup (user_data=<optimized out>) at nm-manager.c:359 #6 0x00007fae967c32a6 in g_main_dispatch (context=0x7fae9aedb180) at gmain.c:3066 #7 g_main_context_dispatch (context=context@entry=0x7fae9aedb180) at gmain.c:3642 #8 0x00007fae967c3628 in g_main_context_iterate (context=0x7fae9aedb180, block=block@entry=1, dispatch=dispatch@entry=1, self=<optimized out>) at gmain.c:3713 #9 0x00007fae967c3a3a in g_main_loop_run (loop=0x7fae9aedb860) at gmain.c:3907 So we need to ref() 'agent' when adding it to pending list, so that the object is not freed if the secret agent unregisters and is removed. Test case: 1. run NM and nm-applet 2. activate a Wi-Fi network 3. nm-applet will ask for a password; ignore the popup window and kill nm-applet 4. start nm-applet again 5. click the same Wi-Fi network in nm-applet 6. NM will experience problems in nm_secret_agent_cancel_secrets() or crashes (the procedure may not be 100%, but reproduces most of the time) https://bugzilla.redhat.com/show_bug.cgi?id=922855
-rw-r--r--src/settings/nm-agent-manager.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/src/settings/nm-agent-manager.c b/src/settings/nm-agent-manager.c
index 8644293db5..7fb8aea29a 100644
--- a/src/settings/nm-agent-manager.c
+++ b/src/settings/nm-agent-manager.c
@@ -492,7 +492,7 @@ request_free (Request *req)
g_free (req->detail);
g_free (req->verb);
- g_slist_free (req->pending);
+ g_slist_free_full (req->pending, g_object_unref);
g_slist_free (req->asked);
memset (req, 0, sizeof (Request));
g_free (req);
@@ -582,7 +582,7 @@ request_add_agent (Request *req,
/* Add this agent to the list, preferring active sessions */
req->pending = g_slist_insert_sorted_with_data (req->pending,
- agent,
+ g_object_ref (agent),
(GCompareDataFunc) agent_compare_func,
session_monitor);
}
@@ -607,6 +607,8 @@ request_next_agent (Request *req)
if (req->pending) {
/* Send the request to the next agent */
req->current_call_id = NULL;
+ if (req->current)
+ g_object_unref (req->current);
req->current = req->pending->data;
req->pending = g_slist_remove (req->pending, req->current);