Skip to content

Commit 4761ed7

Browse files
authored
Merge pull request #4114 from grandixximo/fix/sys-notify-dbus-uaf
qtvcp: fix startup segfault when no notification daemon is present
2 parents b16b011 + 03b7b25 commit 4761ed7

1 file changed

Lines changed: 13 additions & 23 deletions

File tree

lib/python/qtvcp/lib/sys_notify.py

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -61,39 +61,29 @@ def init(app_name):
6161
path = "/org/freedesktop/Notifications"
6262
interface = "org.freedesktop.Notifications"
6363

64-
mainloop = None
65-
bus = None
6664
try:
67-
if DBusQtMainLoop is not None:
68-
mainloop = DBusQtMainLoop(set_as_default=True)
69-
70-
bus = dbus.SessionBus(mainloop)
65+
# Probe on a throwaway no-mainloop connection first. Wiring the
66+
# Qt dbus mainloop before a daemon is confirmed leaves a dangling
67+
# QSocketNotifier that segfaults on its next dispatch.
68+
probe = dbus.SessionBus(private=True)
69+
try:
70+
present = probe.name_has_owner(name)
71+
finally:
72+
probe.close()
73+
if not present:
74+
raise RuntimeError('no notification daemon')
75+
76+
mainloop = DBusQtMainLoop(set_as_default=True) if DBusQtMainLoop else None
77+
bus = dbus.SessionBus(mainloop=mainloop)
7178
proxy = bus.get_object(name, path)
7279
DBUS_IFACE = dbus.Interface(proxy, interface)
7380

7481
if mainloop is not None:
75-
# We have a mainloop, so connect callbacks
7682
DBUS_IFACE.connect_to_signal('ActionInvoked', _onActionInvoked)
7783
DBUS_IFACE.connect_to_signal('NotificationClosed', _onNotificationClosed)
7884
except Exception as e:
7985
LOG.warning('Desktop Notify not available:: {}'.format(e))
80-
# When the SessionBus is constructed with a PyQt5/PyQt6 mainloop
81-
# integration, dbus-python installs a QSocketNotifier on the
82-
# connection fd. If the subsequent get_object/Interface setup
83-
# raises (e.g. ServiceUnknown when no notification daemon owns
84-
# org.freedesktop.Notifications), the Python-side bus reference
85-
# is dropped on exception but the QSocketNotifier keeps the
86-
# underlying C connection alive in a half-initialized state.
87-
# The next QEventLoop tick dispatches a queued message via
88-
# dbus_connection_dispatch() and segfaults inside
89-
# _dbus_list_unlink. Close the bus explicitly so the notifier
90-
# detaches and the connection is fully released.
9186
DBUS_IFACE = None
92-
if bus is not None:
93-
try:
94-
bus.close()
95-
except Exception:
96-
pass
9787

9888

9989
def _onActionInvoked(nid, action):

0 commit comments

Comments
 (0)