Blob Blame History Raw
From e339ad74ca408c665a62bb4bd98dd1ef6caedd20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= <mail@3v1n0.net>
Date: Tue, 27 Oct 2020 15:14:27 +0100
Subject: [PATCH] display: Exit with failure if loading existing users fails

Given not having users may make GDM to launch initial setup, that
allows to create new users (potentially with sudo capabilities), it's
better to make look_for_existing_users() to return its status and only
if it didn't fail continue the gdm execution.

GHSL-2020-202
CVE-2020-16125

Fixes #642
---
 daemon/gdm-display.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 929fa13bd..1b60eb621 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -436,106 +436,110 @@ finish_idle (GdmDisplay *self)
 static void
 queue_finish (GdmDisplay *self)
 {
         if (self->priv->finish_idle_id == 0) {
                 self->priv->finish_idle_id = g_idle_add ((GSourceFunc)finish_idle, self);
         }
 }
 
 static void
 _gdm_display_set_status (GdmDisplay *self,
                          int         status)
 {
         if (status != self->priv->status) {
                 self->priv->status = status;
                 g_object_notify (G_OBJECT (self), "status");
         }
 }
 
 static gboolean
 gdm_display_real_prepare (GdmDisplay *self)
 {
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
 
         g_debug ("GdmDisplay: prepare display");
 
         _gdm_display_set_status (self, GDM_DISPLAY_PREPARED);
 
         return TRUE;
 }
 
-static void
+static gboolean
 look_for_existing_users_sync (GdmDisplay *self)
 {
         g_autoptr (GVariant) result = NULL;
         g_autoptr (GVariant) result_child = NULL;
         g_autoptr (GError) error = NULL;
         gboolean has_no_users = FALSE;
 
         result = g_dbus_connection_call_sync (self->priv->connection,
                                               "org.freedesktop.Accounts",
                                               "/org/freedesktop/Accounts",
                                               "org.freedesktop.DBus.Properties",
                                               "Get",
                                               g_variant_new ("(ss)", "org.freedesktop.Accounts", "HasNoUsers"),
                                               G_VARIANT_TYPE ("(v)"),
                                               G_DBUS_CALL_FLAGS_NONE,
                                               -1,
                                               NULL,
                                               &error);
 
         if (result == NULL) {
-                g_warning ("Failed to contact accountsservice: %s", error->message);
-                return;
+                g_critical ("Failed to contact accountsservice: %s", error->message);
+                goto out;
         }
 
         g_variant_get (result, "(v)", &result_child);
         has_no_users = g_variant_get_boolean (result_child);
         self->priv->have_existing_user_accounts = !has_no_users;
 
         g_debug ("GdmDisplay: machine does %shave existing user accounts",
                  has_no_users? "not " : "");
+out:
+        return result != NULL;
 }
 
 gboolean
 gdm_display_prepare (GdmDisplay *self)
 {
         gboolean ret;
 
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
 
         g_debug ("GdmDisplay: Preparing display: %s", self->priv->id);
 
         /* FIXME: we should probably do this in a more global place,
          * asynchronously
          */
-        look_for_existing_users_sync (self);
+        if (!look_for_existing_users_sync (self)) {
+                exit (EXIT_FAILURE);
+        }
 
         self->priv->doing_initial_setup = wants_initial_setup (self);
 
         g_object_ref (self);
         ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
         g_object_unref (self);
 
         return ret;
 }
 
 gboolean
 gdm_display_manage (GdmDisplay *self)
 {
         gboolean res;
 
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
 
         g_debug ("GdmDisplay: Managing display: %s", self->priv->id);
 
         /* If not explicitly prepared, do it now */
         if (self->priv->status == GDM_DISPLAY_UNMANAGED) {
                 res = gdm_display_prepare (self);
                 if (! res) {
                         return FALSE;
                 }
         }
 
         if (g_strcmp0 (self->priv->session_class, "greeter") == 0) {
                 if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
                         GDM_DISPLAY_GET_CLASS (self)->manage (self);
-- 
2.28.0