mirror of
https://github.com/pi-hole/dnsmasq.git
synced 2025-12-19 18:28:25 +00:00
Fix crash in dbus code.
If I configure dnsmasq to use dbus and then restart dbus.service with watchers present, it crashes dnsmasq. The reason is simple, it uses loop to walk over watchers to call dbus handling code. But from that code the same list can be modified and watchers removed. But the list iteration continues anyway. Restart the loop if list were modified.
This commit is contained in:
committed by
Simon Kelley
parent
bd188e306a
commit
33635d8564
22
src/dbus.c
22
src/dbus.c
@@ -106,6 +106,7 @@ const char* introspection_xml_template =
|
|||||||
"</node>\n";
|
"</node>\n";
|
||||||
|
|
||||||
static char *introspection_xml = NULL;
|
static char *introspection_xml = NULL;
|
||||||
|
static int watches_modified = 0;
|
||||||
|
|
||||||
struct watch {
|
struct watch {
|
||||||
DBusWatch *watch;
|
DBusWatch *watch;
|
||||||
@@ -127,6 +128,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
|||||||
w->watch = watch;
|
w->watch = watch;
|
||||||
w->next = daemon->watches;
|
w->next = daemon->watches;
|
||||||
daemon->watches = w;
|
daemon->watches = w;
|
||||||
|
watches_modified++;
|
||||||
|
|
||||||
(void)data; /* no warning */
|
(void)data; /* no warning */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -143,6 +145,7 @@ static void remove_watch(DBusWatch *watch, void *data)
|
|||||||
{
|
{
|
||||||
*up = tmp;
|
*up = tmp;
|
||||||
free(w);
|
free(w);
|
||||||
|
watches_modified++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
up = &(w->next);
|
up = &(w->next);
|
||||||
@@ -966,11 +969,11 @@ void set_dbus_listeners(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_dbus_listeners()
|
static int check_dbus_watches()
|
||||||
{
|
{
|
||||||
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
|
||||||
struct watch *w;
|
struct watch *w;
|
||||||
|
|
||||||
|
watches_modified = 0;
|
||||||
for (w = daemon->watches; w; w = w->next)
|
for (w = daemon->watches; w; w = w->next)
|
||||||
if (dbus_watch_get_enabled(w->watch))
|
if (dbus_watch_get_enabled(w->watch))
|
||||||
{
|
{
|
||||||
@@ -987,9 +990,22 @@ void check_dbus_listeners()
|
|||||||
flags |= DBUS_WATCH_ERROR;
|
flags |= DBUS_WATCH_ERROR;
|
||||||
|
|
||||||
if (flags != 0)
|
if (flags != 0)
|
||||||
dbus_watch_handle(w->watch, flags);
|
{
|
||||||
|
dbus_watch_handle(w->watch, flags);
|
||||||
|
if (watches_modified)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void check_dbus_listeners()
|
||||||
|
{
|
||||||
|
DBusConnection *connection = (DBusConnection *)daemon->dbus;
|
||||||
|
|
||||||
|
while (!check_dbus_watches()) ;
|
||||||
|
|
||||||
if (connection)
|
if (connection)
|
||||||
{
|
{
|
||||||
dbus_connection_ref (connection);
|
dbus_connection_ref (connection);
|
||||||
|
|||||||
Reference in New Issue
Block a user