8884c34
From fd19aaaa097e71e7589bdb3627971dc10bf3873e Mon Sep 17 00:00:00 2001
d448651
From: fujiwarat <takao.fujiwara1@gmail.com>
8884c34
Date: Thu, 13 Feb 2020 19:33:32 +0900
0e0ffba
Subject: [PATCH] Fix SEGV in bus_panel_proxy_focus_in()
0e0ffba
0e0ffba
rhbz#1349148, rhbz#1385349
0e0ffba
SEGV in BUS_IS_PANEL_PROXY() in bus_panel_proxy_focus_in()
0e0ffba
Check if GDBusConnect is closed before bus_panel_proxy_new() is called.
0e0ffba
0e0ffba
rhbz#1350291 SEGV in BUS_IS_CONNECTION(skip_connection) in
0e0ffba
bus_dbus_impl_dispatch_message_by_rule()
0e0ffba
check if dbus_connection is closed in bus_dbus_impl_connection_filter_cb().
0e0ffba
0e0ffba
rhbz#1406699 SEGV in new_owner!=NULL in bus_dbus_impl_name_owner_changed()
0e0ffba
which is called by bus_name_service_remove_owner()
0e0ffba
If bus_connection_get_unique_name()==NULL, set new_owner="" in
0e0ffba
bus_name_service_remove_owner()
0e0ffba
0e0ffba
rhbz#1432252 SEGV in old_owner!=NULL in bus_dbus_impl_name_owner_changed()
0e0ffba
which is called by bus_name_service_set_primary_owner()
0e0ffba
If bus_connection_get_unique_name()==NULL, set old_owner="" in
0e0ffba
bus_name_service_set_primary_owner()
0e0ffba
0e0ffba
rhbz#1601577 SEGV in ibus_engine_desc_get_layout() in
0e0ffba
bus_engine_proxy_new_internal()
0e0ffba
WIP: Added a GError to get the error message to check why the SEGV happened.
0e0ffba
0e0ffba
rhbz#1663528 SEGV in g_mutex_clear() in bus_dbus_impl_destroy()
0e0ffba
If the mutex is not unlocked, g_mutex_clear() causes assert.
d448651
8884c34
rhbz#1767691 SEGV in client/x11/main.c:_sighandler().
8884c34
Do not call atexit functions in _sighandler().
8884c34
8884c34
rhbz#1795499 SEGV in ibus_bus_get_bus_address() because of no _bus->priv.
8884c34
_changed_cb() should not be called after ibus_bus_destroy() is called.
8884c34
d448651
BUG=rhbz#1349148
d448651
BUG=rhbz#1385349
d448651
BUG=rhbz#1350291
3818b86
BUG=rhbz#1406699
3818b86
BUG=rhbz#1432252
d165013
BUG=rhbz#1601577
0e0ffba
BUG=rhbz#1663528
8884c34
BUG=rhbz#1767691
8884c34
BUG=rhbz#1795499
d448651
---
769eef0
 bus/dbusimpl.c    | 70 +++++++++++++++++++++++++++++++++++++++++------
769eef0
 bus/engineproxy.c |  9 +++++-
769eef0
 bus/ibusimpl.c    | 21 ++++++++++++--
8884c34
 client/x11/main.c |  8 +++++-
8884c34
 src/ibusbus.c     |  5 ++++
8884c34
 5 files changed, 100 insertions(+), 13 deletions(-)
d448651
d448651
diff --git a/bus/dbusimpl.c b/bus/dbusimpl.c
769eef0
index b54ef817..fb38faf0 100644
d448651
--- a/bus/dbusimpl.c
d448651
+++ b/bus/dbusimpl.c
d448651
@@ -2,7 +2,8 @@
d448651
 /* vim:set et sts=4: */
d448651
 /* ibus - The Input Bus
d448651
  * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
d448651
- * Copyright (C) 2008-2013 Red Hat, Inc.
0e0ffba
+ * Copyright (C) 2015-2019 Takao Fujiwara <takao.fujiwara1@gmail.com>
0e0ffba
+ * Copyright (C) 2008-2019 Red Hat, Inc.
d448651
  *
d448651
  * This library is free software; you can redistribute it and/or
d448651
  * modify it under the terms of the GNU Lesser General Public
769eef0
@@ -344,6 +345,8 @@ bus_name_service_set_primary_owner (BusNameService     *service,
3818b86
                                     BusConnectionOwner *owner,
3818b86
                                     BusDBusImpl        *dbus)
3818b86
 {
3818b86
+    gboolean has_old_owner = FALSE;
3818b86
+
3818b86
     g_assert (service != NULL);
3818b86
     g_assert (owner != NULL);
3818b86
     g_assert (dbus != NULL);
769eef0
@@ -351,6 +354,13 @@ bus_name_service_set_primary_owner (BusNameService     *service,
3818b86
     BusConnectionOwner *old = service->owners != NULL ?
3818b86
             (BusConnectionOwner *)service->owners->data : NULL;
3818b86
 
3818b86
+    /* rhbz#1432252 If bus_connection_get_unique_name() == NULL,
3818b86
+     * "Hello" method is not received yet.
3818b86
+     */
3818b86
+    if (old != NULL && bus_connection_get_unique_name (old->conn) != NULL) {
3818b86
+        has_old_owner = TRUE;
3818b86
+    }
3818b86
+
3818b86
     if (old != NULL) {
3818b86
         g_signal_emit (dbus,
3818b86
                        dbus_signals[NAME_LOST],
769eef0
@@ -370,7 +380,8 @@ bus_name_service_set_primary_owner (BusNameService     *service,
3818b86
                    0,
3818b86
                    owner->conn,
3818b86
                    service->name,
3818b86
-                   old != NULL ? bus_connection_get_unique_name (old->conn) : "",
3818b86
+                   has_old_owner ? bus_connection_get_unique_name (old->conn) :
3818b86
+                           "",
3818b86
                    bus_connection_get_unique_name (owner->conn));
3818b86
 
3818b86
     if (old != NULL && old->do_not_queue != 0) {
769eef0
@@ -427,6 +438,7 @@ bus_name_service_remove_owner (BusNameService     *service,
3818b86
                                BusDBusImpl        *dbus)
3818b86
 {
3818b86
     GSList *owners;
3818b86
+    gboolean has_new_owner = FALSE;
3818b86
 
3818b86
     g_assert (service != NULL);
3818b86
     g_assert (owner != NULL);
769eef0
@@ -439,6 +451,13 @@ bus_name_service_remove_owner (BusNameService     *service,
3818b86
         BusConnectionOwner *_new = NULL;
3818b86
         if (owners->next != NULL) {
3818b86
             _new = (BusConnectionOwner *)owners->next->data;
3818b86
+            /* rhbz#1406699 If bus_connection_get_unique_name() == NULL,
3818b86
+             * "Hello" method is not received yet.
3818b86
+             */
3818b86
+            if (_new != NULL &&
3818b86
+                bus_connection_get_unique_name (_new->conn) != NULL) {
3818b86
+                has_new_owner = TRUE;
3818b86
+            }
3818b86
         }
3818b86
 
3818b86
         if (dbus != NULL) {
769eef0
@@ -447,7 +466,7 @@ bus_name_service_remove_owner (BusNameService     *service,
3818b86
                            0,
3818b86
                            owner->conn,
3818b86
                            service->name);
3818b86
-            if (_new != NULL) {
3818b86
+            if (has_new_owner) {
3818b86
                 g_signal_emit (dbus,
3818b86
                                dbus_signals[NAME_ACQUIRED],
3818b86
                                0,
769eef0
@@ -460,7 +479,7 @@ bus_name_service_remove_owner (BusNameService     *service,
3818b86
                     _new != NULL ? _new->conn : NULL,
3818b86
                     service->name,
3818b86
                     bus_connection_get_unique_name (owner->conn),
3818b86
-                    _new != NULL ? bus_connection_get_unique_name (_new->conn) : "");
3818b86
+                    has_new_owner ? bus_connection_get_unique_name (_new->conn) : "");
3818b86
 
3818b86
         }
3818b86
     }
769eef0
@@ -591,6 +610,7 @@ static void
769eef0
 bus_dbus_impl_destroy (BusDBusImpl *dbus)
769eef0
 {
769eef0
     GList *p;
769eef0
+    int i;
0e0ffba
 
769eef0
     for (p = dbus->objects; p != NULL; p = p->next) {
769eef0
         IBusService *object = (IBusService *) p->data;
769eef0
@@ -628,12 +648,39 @@ bus_dbus_impl_destroy (BusDBusImpl *dbus)
769eef0
     dbus->unique_names = NULL;
769eef0
     dbus->names = NULL;
0e0ffba
 
769eef0
+    for (i = 0; g_idle_remove_by_data (dbus); i++) {
769eef0
+        if (i > 1000) {
769eef0
+            g_warning ("Too many idle threads were generated by " \
769eef0
+                       "bus_dbus_impl_forward_message_idle_cb and " \
769eef0
+                       "bus_dbus_impl_dispatch_message_by_rule_idle_cb");
769eef0
+            break;
769eef0
+        }
769eef0
+    }
769eef0
     g_list_free_full (dbus->start_service_calls,
0e0ffba
                       (GDestroyNotify) bus_method_call_free);
0e0ffba
     dbus->start_service_calls = NULL;
0e0ffba
 
0e0ffba
-    g_mutex_clear (&dbus->dispatch_lock);
0e0ffba
-    g_mutex_clear (&dbus->forward_lock);
769eef0
+   /* rhbz#1663528 Call g_mutex_trylock() before g_mutex_clear()
769eef0
+    * because if the mutex is not unlocked, g_mutex_clear() causes assert.
769eef0
+    */
769eef0
+#define BUS_DBUS_MUTEX_SAFE_CLEAR(mtex) {                               \
769eef0
+    int count = 0;                                                      \
769eef0
+    while (!g_mutex_trylock ((mtex))) {                                 \
769eef0
+        g_usleep (1);                                                   \
769eef0
+        if (count > 60) {                                               \
769eef0
+            g_warning (#mtex " is dead lock");                          \
769eef0
+            break;                                                      \
769eef0
+        }                                                               \
769eef0
+        ++count;                                                        \
769eef0
+    }                                                                   \
769eef0
+    g_mutex_unlock ((mtex));                                            \
769eef0
+    g_mutex_clear ((mtex));                                             \
769eef0
+}
0e0ffba
+
769eef0
+    BUS_DBUS_MUTEX_SAFE_CLEAR (&dbus->dispatch_lock);
769eef0
+    BUS_DBUS_MUTEX_SAFE_CLEAR (&dbus->forward_lock);
769eef0
+
769eef0
+#undef BUS_DBUS_MUTEX_SAFE_CLEAR
0e0ffba
 
0e0ffba
     /* FIXME destruct _lock and _queue members. */
0e0ffba
     IBUS_OBJECT_CLASS(bus_dbus_impl_parent_class)->destroy ((IBusObject *) dbus);
769eef0
@@ -1464,13 +1511,20 @@ bus_dbus_impl_connection_filter_cb (GDBusConnection *dbus_connection,
d448651
                                     gboolean         incoming,
d448651
                                     gpointer         user_data)
d448651
 {
d448651
+    BusDBusImpl *dbus;
d448651
+    BusConnection *connection;
d448651
+
d448651
     g_assert (G_IS_DBUS_CONNECTION (dbus_connection));
d448651
     g_assert (G_IS_DBUS_MESSAGE (message));
d448651
     g_assert (BUS_IS_DBUS_IMPL (user_data));
d448651
 
d448651
-    BusDBusImpl *dbus = (BusDBusImpl *) user_data;
d448651
-    BusConnection *connection = bus_connection_lookup (dbus_connection);
d448651
+    if (g_dbus_connection_is_closed (dbus_connection))
d448651
+        return NULL;
d448651
+
d448651
+    dbus = (BusDBusImpl *) user_data;
d448651
+    connection = bus_connection_lookup (dbus_connection);
d448651
     g_assert (connection != NULL);
d448651
+    g_assert (BUS_IS_CONNECTION (connection));
d448651
 
d448651
     if (incoming) {
d448651
         /* is incoming message */
d165013
diff --git a/bus/engineproxy.c b/bus/engineproxy.c
0e0ffba
index 2d98995c..2176e0c9 100644
d165013
--- a/bus/engineproxy.c
d165013
+++ b/bus/engineproxy.c
d165013
@@ -665,6 +665,7 @@ bus_engine_proxy_new_internal (const gchar     *path,
d165013
                                IBusEngineDesc  *desc,
d165013
                                GDBusConnection *connection)
d165013
 {
d165013
+    GError *error = NULL;
d165013
     g_assert (path);
d165013
     g_assert (IBUS_IS_ENGINE_DESC (desc));
d165013
     g_assert (G_IS_DBUS_CONNECTION (connection));
d165013
@@ -673,7 +674,7 @@ bus_engine_proxy_new_internal (const gchar     *path,
d165013
     BusEngineProxy *engine =
d165013
         (BusEngineProxy *) g_initable_new (BUS_TYPE_ENGINE_PROXY,
d165013
                                            NULL,
d165013
-                                           NULL,
d165013
+                                           &error,
d165013
                                            "desc",              desc,
d165013
                                            "g-connection",      connection,
d165013
                                            "g-interface-name",  IBUS_INTERFACE_ENGINE,
0e0ffba
@@ -681,6 +682,12 @@ bus_engine_proxy_new_internal (const gchar     *path,
d165013
                                            "g-default-timeout", g_gdbus_timeout,
d165013
                                            "g-flags",           flags,
d165013
                                            NULL);
d165013
+    /* FIXME: rhbz#1601577 */
0e0ffba
+    if (error) {
0e0ffba
+        /* show abrt local variable */
0e0ffba
+        gchar *message = g_strdup (error->message);
0e0ffba
+        g_error ("%s", message);
0e0ffba
+    }
d165013
     const gchar *layout = ibus_engine_desc_get_layout (desc);
d165013
     if (layout != NULL && layout[0] != '\0') {
d165013
         engine->keymap = ibus_keymap_get (layout);
d448651
diff --git a/bus/ibusimpl.c b/bus/ibusimpl.c
8884c34
index 85761d30..f0dbccd1 100644
d448651
--- a/bus/ibusimpl.c
d448651
+++ b/bus/ibusimpl.c
0e0ffba
@@ -464,13 +464,16 @@ _dbus_name_owner_changed_cb (BusDBusImpl   *dbus,
6784864
     else if (!g_strcmp0 (name, IBUS_SERVICE_PANEL_EXTENSION_EMOJI))
6784864
         panel_type = PANEL_TYPE_EXTENSION_EMOJI;
d448651
 
98919f7
-    if (panel_type != PANEL_TYPE_NONE) {
d448651
+    do {
98919f7
+        if (panel_type == PANEL_TYPE_NONE)
d448651
+            break;
d448651
         if (g_strcmp0 (new_name, "") != 0) {
d448651
             /* a Panel process is started. */
d448651
             BusConnection *connection;
d448651
             BusInputContext *context = NULL;
98919f7
             BusPanelProxy   **panel = (panel_type == PANEL_TYPE_PANEL) ?
6784864
                                       &ibus->panel : &ibus->emoji_extension;
d448651
+            GDBusConnection *dbus_connection = NULL;
d448651
 
98919f7
             if (*panel != NULL) {
98919f7
                 ibus_proxy_destroy ((IBusProxy *)(*panel));
0e0ffba
@@ -479,9 +482,21 @@ _dbus_name_owner_changed_cb (BusDBusImpl   *dbus,
98919f7
                 g_assert (*panel == NULL);
98919f7
             }
98919f7
 
98919f7
-            connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
98919f7
+            connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS,
98919f7
+                                                               new_name);
d448651
             g_return_if_fail (connection != NULL);
d448651
 
d448651
+            dbus_connection = bus_connection_get_dbus_connection (connection);
d448651
+            /* rhbz#1349148 rhbz#1385349
d448651
+             * Avoid SEGV of BUS_IS_PANEL_PROXY (ibus->panel)
d448651
+             * This function is called during destroying the connection
d448651
+             * in this case? */
d448651
+            if (dbus_connection == NULL ||
d448651
+                g_dbus_connection_is_closed (dbus_connection)) {
d448651
+                new_name = "";
d448651
+                break;
d448651
+            }
d448651
+
98919f7
             *panel = bus_panel_proxy_new (connection, panel_type);
6784864
             if (panel_type == PANEL_TYPE_EXTENSION_EMOJI)
6784864
                 ibus->enable_emoji_extension = FALSE;
0e0ffba
@@ -535,7 +550,7 @@ _dbus_name_owner_changed_cb (BusDBusImpl   *dbus,
d448651
                 }
d448651
             }
d448651
         }
d448651
-    }
d448651
+    } while (0);
d448651
 
d448651
     bus_ibus_impl_component_name_owner_changed (ibus, name, old_name, new_name);
d448651
 }
8884c34
diff --git a/client/x11/main.c b/client/x11/main.c
8884c34
index c9ee174d..768b91f0 100644
8884c34
--- a/client/x11/main.c
8884c34
+++ b/client/x11/main.c
8884c34
@@ -40,6 +40,7 @@
8884c34
 #include <iconv.h>
8884c34
 #include <signal.h>
8884c34
 #include <stdlib.h>
8884c34
+#include <unistd.h>
8884c34
 
8884c34
 #include <getopt.h>
8884c34
 
8884c34
@@ -1104,7 +1105,12 @@ _atexit_cb ()
8884c34
 static void
8884c34
 _sighandler (int sig)
8884c34
 {
8884c34
-    exit(EXIT_FAILURE);
8884c34
+    /* rhbz#1767691 _sighandler() is called with SIGTERM
8884c34
+     * and exit() causes SEGV during calling atexit functions.
8884c34
+     * _atexit_cb() might be broken. _exit() does not call
8884c34
+     * atexit functions.
8884c34
+     */
8884c34
+    _exit(EXIT_FAILURE);
8884c34
 }
8884c34
 
8884c34
 static void
8884c34
diff --git a/src/ibusbus.c b/src/ibusbus.c
8884c34
index b7ffbb47..668c8a26 100644
8884c34
--- a/src/ibusbus.c
8884c34
+++ b/src/ibusbus.c
8884c34
@@ -689,6 +689,11 @@ ibus_bus_destroy (IBusObject *object)
8884c34
     _bus = NULL;
8884c34
 
8884c34
     if (bus->priv->monitor) {
8884c34
+        /* rhbz#1795499 _changed_cb() causes SEGV because of no bus->priv
8884c34
+         * after ibus_bus_destroy() is called.
8884c34
+         */
8884c34
+        g_signal_handlers_disconnect_by_func (bus->priv->monitor,
8884c34
+                                              (GCallback) _changed_cb, bus);
8884c34
         g_object_unref (bus->priv->monitor);
8884c34
         bus->priv->monitor = NULL;
8884c34
     }
d448651
-- 
8884c34
2.24.1
d448651