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
This commit is contained in:
Jiří Klimeš 2013-11-21 13:40:04 +01:00
parent 593f1aadec
commit 91a95dd916

View file

@ -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);