Blame SOURCES/0001-display-Exit-with-failure-if-loading-existing-users-.patch

400dab
From e339ad74ca408c665a62bb4bd98dd1ef6caedd20 Mon Sep 17 00:00:00 2001
400dab
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
400dab
Date: Tue, 27 Oct 2020 15:14:27 +0100
400dab
Subject: [PATCH] display: Exit with failure if loading existing users fails
400dab
400dab
Given not having users may make GDM to launch initial setup, that
400dab
allows to create new users (potentially with sudo capabilities), it's
400dab
better to make look_for_existing_users() to return its status and only
400dab
if it didn't fail continue the gdm execution.
400dab
400dab
GHSL-2020-202
400dab
CVE-2020-16125
400dab
400dab
Fixes #642
400dab
---
400dab
 daemon/gdm-display.c | 12 ++++++++----
400dab
 1 file changed, 8 insertions(+), 4 deletions(-)
400dab
400dab
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
400dab
index 929fa13bd..1b60eb621 100644
400dab
--- a/daemon/gdm-display.c
400dab
+++ b/daemon/gdm-display.c
400dab
@@ -436,106 +436,110 @@ finish_idle (GdmDisplay *self)
400dab
 static void
400dab
 queue_finish (GdmDisplay *self)
400dab
 {
400dab
         if (self->priv->finish_idle_id == 0) {
400dab
                 self->priv->finish_idle_id = g_idle_add ((GSourceFunc)finish_idle, self);
400dab
         }
400dab
 }
400dab
 
400dab
 static void
400dab
 _gdm_display_set_status (GdmDisplay *self,
400dab
                          int         status)
400dab
 {
400dab
         if (status != self->priv->status) {
400dab
                 self->priv->status = status;
400dab
                 g_object_notify (G_OBJECT (self), "status");
400dab
         }
400dab
 }
400dab
 
400dab
 static gboolean
400dab
 gdm_display_real_prepare (GdmDisplay *self)
400dab
 {
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         g_debug ("GdmDisplay: prepare display");
400dab
 
400dab
         _gdm_display_set_status (self, GDM_DISPLAY_PREPARED);
400dab
 
400dab
         return TRUE;
400dab
 }
400dab
 
400dab
-static void
400dab
+static gboolean
400dab
 look_for_existing_users_sync (GdmDisplay *self)
400dab
 {
400dab
         g_autoptr (GVariant) result = NULL;
400dab
         g_autoptr (GVariant) result_child = NULL;
400dab
         g_autoptr (GError) error = NULL;
400dab
         gboolean has_no_users = FALSE;
400dab
 
400dab
         result = g_dbus_connection_call_sync (self->priv->connection,
400dab
                                               "org.freedesktop.Accounts",
400dab
                                               "/org/freedesktop/Accounts",
400dab
                                               "org.freedesktop.DBus.Properties",
400dab
                                               "Get",
400dab
                                               g_variant_new ("(ss)", "org.freedesktop.Accounts", "HasNoUsers"),
400dab
                                               G_VARIANT_TYPE ("(v)"),
400dab
                                               G_DBUS_CALL_FLAGS_NONE,
400dab
                                               -1,
400dab
                                               NULL,
400dab
                                               &error);
400dab
 
400dab
         if (result == NULL) {
400dab
-                g_warning ("Failed to contact accountsservice: %s", error->message);
400dab
-                return;
400dab
+                g_critical ("Failed to contact accountsservice: %s", error->message);
400dab
+                goto out;
400dab
         }
400dab
 
400dab
         g_variant_get (result, "(v)", &result_child);
400dab
         has_no_users = g_variant_get_boolean (result_child);
400dab
         self->priv->have_existing_user_accounts = !has_no_users;
400dab
 
400dab
         g_debug ("GdmDisplay: machine does %shave existing user accounts",
400dab
                  has_no_users? "not " : "");
400dab
+out:
400dab
+        return result != NULL;
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_prepare (GdmDisplay *self)
400dab
 {
400dab
         gboolean ret;
400dab
 
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         g_debug ("GdmDisplay: Preparing display: %s", self->priv->id);
400dab
 
400dab
         /* FIXME: we should probably do this in a more global place,
400dab
          * asynchronously
400dab
          */
400dab
-        look_for_existing_users_sync (self);
400dab
+        if (!look_for_existing_users_sync (self)) {
400dab
+                exit (EXIT_FAILURE);
400dab
+        }
400dab
 
400dab
         self->priv->doing_initial_setup = wants_initial_setup (self);
400dab
 
400dab
         g_object_ref (self);
400dab
         ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
400dab
         g_object_unref (self);
400dab
 
400dab
         return ret;
400dab
 }
400dab
 
400dab
 gboolean
400dab
 gdm_display_manage (GdmDisplay *self)
400dab
 {
400dab
         gboolean res;
400dab
 
400dab
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
400dab
 
400dab
         g_debug ("GdmDisplay: Managing display: %s", self->priv->id);
400dab
 
400dab
         /* If not explicitly prepared, do it now */
400dab
         if (self->priv->status == GDM_DISPLAY_UNMANAGED) {
400dab
                 res = gdm_display_prepare (self);
400dab
                 if (! res) {
400dab
                         return FALSE;
400dab
                 }
400dab
         }
400dab
 
400dab
         if (g_strcmp0 (self->priv->session_class, "greeter") == 0) {
400dab
                 if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
400dab
                         GDM_DISPLAY_GET_CLASS (self)->manage (self);
400dab
-- 
400dab
2.28.0
400dab