dnsmasq/dnsmasq-2.90-dbus-watchers-bz2186468.patch
2023-04-27 11:46:29 +02:00

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