From 2b54bd6a53b165f12b8eefe5232ea20cc9d3440c Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Tue, 12 Jan 2016 16:06:21 +0100 Subject: [PATCH] dispatcher: fix use-after-free in complete_script() complete_request() possibly frees the request, making the @script and @request a dangling pointer. We must not use those pointers, except a plain pointer- comparison. --- callouts/nm-dispatcher.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/callouts/nm-dispatcher.c b/callouts/nm-dispatcher.c index 7106103e3..43d34eb7e 100644 --- a/callouts/nm-dispatcher.c +++ b/callouts/nm-dispatcher.c @@ -323,21 +323,25 @@ static void complete_script (ScriptInfo *script) { Handler *handler; + Request *request; gboolean wait = script->wait; + request = script->request; + if (wait) { /* for "wait" scripts, try to schedule the next blocking script. * If that is successful, return (as we must wait for its completion). */ - if (dispatch_one_script (script->request)) + if (dispatch_one_script (request)) return; } - handler = script->request->handler; + handler = request->handler; - nm_assert (!wait || handler->current_request == script->request); + nm_assert (!wait || handler->current_request == request); - /* Try to complete the request. */ - complete_request (script->request); + /* Try to complete the request. @request will be possibly free'd, + * making @script and @request a dangling pointer. */ + complete_request (request); if (!wait) { /* this was a "no-wait" script. We either completed the request, @@ -346,20 +350,18 @@ complete_script (ScriptInfo *script) * requests. However, if this was the last "no-wait" script and * there are "wait" scripts ready to run, launch them. */ - if ( handler->current_request == script->request - && script->request->num_scripts_nowait == 0) { + if ( handler->current_request == request + && handler->current_request->num_scripts_nowait == 0) { - if (dispatch_one_script (script->request)) + if (dispatch_one_script (handler->current_request)) return; - complete_request (script->request); + complete_request (handler->current_request); } else return; } while (next_request (handler, NULL)) { - Request *request; - request = handler->current_request; if (dispatch_one_script (request))