94 lines
2.4 KiB
Diff
94 lines
2.4 KiB
Diff
From 33635d8564f96cedcef9bf9826cbbca76f28aa81 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Petr=20Men=C5=A1=C3=ADk?= <pemensik@redhat.com>
|
|
Date: Mon, 17 Apr 2023 20:55:31 +0100
|
|
Subject: [PATCH] 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.
|
|
---
|
|
src/dbus.c | 24 ++++++++++++++++++++----
|
|
1 file changed, 20 insertions(+), 4 deletions(-)
|
|
|
|
diff --git a/src/dbus.c b/src/dbus.c
|
|
index 24efcb8..34cf2f6 100644
|
|
--- a/src/dbus.c
|
|
+++ b/src/dbus.c
|
|
@@ -106,6 +106,7 @@ const char* introspection_xml_template =
|
|
"</node>\n";
|
|
|
|
static char *introspection_xml = NULL;
|
|
+static int watches_modified = 0;
|
|
|
|
struct watch {
|
|
DBusWatch *watch;
|
|
@@ -127,6 +128,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
|
w->watch = watch;
|
|
w->next = daemon->watches;
|
|
daemon->watches = w;
|
|
+ watches_modified++;
|
|
|
|
(void)data; /* no warning */
|
|
return TRUE;
|
|
@@ -134,7 +136,7 @@ static dbus_bool_t add_watch(DBusWatch *watch, void *data)
|
|
|
|
static void remove_watch(DBusWatch *watch, void *data)
|
|
{
|
|
- struct watch **up, *w, *tmp;
|
|
+ struct watch **up, *w, *tmp;
|
|
|
|
for (up = &(daemon->watches), w = daemon->watches; w; w = tmp)
|
|
{
|
|
@@ -143,6 +145,7 @@ static void remove_watch(DBusWatch *watch, void *data)
|
|
{
|
|
*up = tmp;
|
|
free(w);
|
|
+ watches_modified++;
|
|
}
|
|
else
|
|
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;
|
|
|
|
+ watches_modified = 0;
|
|
for (w = daemon->watches; w; w = w->next)
|
|
if (dbus_watch_get_enabled(w->watch))
|
|
{
|
|
@@ -987,9 +990,22 @@ void check_dbus_listeners()
|
|
flags |= DBUS_WATCH_ERROR;
|
|
|
|
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)
|
|
{
|
|
dbus_connection_ref (connection);
|
|
--
|
|
2.40.0
|
|
|