From e339ad74ca408c665a62bb4bd98dd1ef6caedd20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= 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