import gdm-3.28.3-39.el8
This commit is contained in:
parent
e563a6593a
commit
10d480e908
@ -1,4 +1,4 @@
|
||||
From 29d374ce6781df6f3b168a8c57163ddb582c998a Mon Sep 17 00:00:00 2001
|
||||
From 53c549876bcb7363d1d6dca70f2e1d3889741a06 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Wed, 31 Jul 2013 17:32:55 -0400
|
||||
Subject: [PATCH] data: add system dconf databases to gdm profile
|
||||
@ -9,14 +9,16 @@ This way system settings can affect the login screen.
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
diff --git a/data/dconf/gdm.in b/data/dconf/gdm.in
|
||||
index 4d8bf174..9694078f 100644
|
||||
index 4d8bf1748..606e0b863 100644
|
||||
--- a/data/dconf/gdm.in
|
||||
+++ b/data/dconf/gdm.in
|
||||
@@ -1,2 +1,5 @@
|
||||
@@ -1,2 +1,6 @@
|
||||
user-db:user
|
||||
+system-db:gdm
|
||||
+system-db:local
|
||||
+system-db:site
|
||||
+system-db:distro
|
||||
file-db:@DATADIR@/@PACKAGE@/greeter-dconf-defaults
|
||||
--
|
||||
2.11.1
|
||||
--
|
||||
2.26.0
|
||||
|
@ -0,0 +1,140 @@
|
||||
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
|
||||
|
@ -0,0 +1,433 @@
|
||||
From a9422c7b5f4200ad36300bb06134d545bb9d48d2 Mon Sep 17 00:00:00 2001
|
||||
From: Lubomir Rintel <lkundrak@v3.sk>
|
||||
Date: Tue, 17 Jul 2018 20:20:55 +0000
|
||||
Subject: [PATCH 01/51] display-factory: avoid removing a display from store
|
||||
while iterating it
|
||||
|
||||
---
|
||||
daemon/gdm-display-factory.c | 41 ++++++++++++++++++++++++++++++
|
||||
daemon/gdm-display-factory.h | 1 +
|
||||
daemon/gdm-local-display-factory.c | 7 ++---
|
||||
daemon/gdm-xdmcp-display-factory.c | 7 ++---
|
||||
4 files changed, 46 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-display-factory.c b/daemon/gdm-display-factory.c
|
||||
index d86a4c8ad..c520e1088 100644
|
||||
--- a/daemon/gdm-display-factory.c
|
||||
+++ b/daemon/gdm-display-factory.c
|
||||
@@ -8,84 +8,120 @@
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "gdm-display-factory.h"
|
||||
#include "gdm-display-store.h"
|
||||
|
||||
#define GDM_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY_FACTORY, GdmDisplayFactoryPrivate))
|
||||
|
||||
struct GdmDisplayFactoryPrivate
|
||||
{
|
||||
GdmDisplayStore *display_store;
|
||||
+ guint purge_displays_id;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_DISPLAY_STORE,
|
||||
};
|
||||
|
||||
static void gdm_display_factory_class_init (GdmDisplayFactoryClass *klass);
|
||||
static void gdm_display_factory_init (GdmDisplayFactory *factory);
|
||||
static void gdm_display_factory_finalize (GObject *object);
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (GdmDisplayFactory, gdm_display_factory, G_TYPE_OBJECT)
|
||||
|
||||
GQuark
|
||||
gdm_display_factory_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
if (ret == 0) {
|
||||
ret = g_quark_from_static_string ("gdm_display_factory_error");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+purge_display (char *id,
|
||||
+ GdmDisplay *display,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ int status;
|
||||
+
|
||||
+ status = gdm_display_get_status (display);
|
||||
+
|
||||
+ switch (status) {
|
||||
+ case GDM_DISPLAY_FINISHED:
|
||||
+ case GDM_DISPLAY_FAILED:
|
||||
+ return TRUE;
|
||||
+ default:
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+purge_displays (GdmDisplayFactory *factory)
|
||||
+{
|
||||
+ factory->priv->purge_displays_id = 0;
|
||||
+ gdm_display_store_foreach_remove (factory->priv->display_store,
|
||||
+ (GdmDisplayStoreFunc)purge_display,
|
||||
+ NULL);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+gdm_display_factory_queue_purge_displays (GdmDisplayFactory *factory)
|
||||
+{
|
||||
+ if (factory->priv->purge_displays_id == 0) {
|
||||
+ factory->priv->purge_displays_id = g_idle_add ((GSourceFunc) purge_displays, factory);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
GdmDisplayStore *
|
||||
gdm_display_factory_get_display_store (GdmDisplayFactory *factory)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), NULL);
|
||||
|
||||
return factory->priv->display_store;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_display_factory_start (GdmDisplayFactory *factory)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
|
||||
|
||||
g_object_ref (factory);
|
||||
ret = GDM_DISPLAY_FACTORY_GET_CLASS (factory)->start (factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_display_factory_stop (GdmDisplayFactory *factory)
|
||||
{
|
||||
gboolean ret;
|
||||
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
|
||||
|
||||
g_object_ref (factory);
|
||||
@@ -160,32 +196,37 @@ gdm_display_factory_class_init (GdmDisplayFactoryClass *klass)
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DISPLAY_STORE,
|
||||
g_param_spec_object ("display-store",
|
||||
"display store",
|
||||
"display store",
|
||||
GDM_TYPE_DISPLAY_STORE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GdmDisplayFactoryPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_display_factory_init (GdmDisplayFactory *factory)
|
||||
{
|
||||
factory->priv = GDM_DISPLAY_FACTORY_GET_PRIVATE (factory);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_display_factory_finalize (GObject *object)
|
||||
{
|
||||
GdmDisplayFactory *factory;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GDM_IS_DISPLAY_FACTORY (object));
|
||||
|
||||
factory = GDM_DISPLAY_FACTORY (object);
|
||||
|
||||
g_return_if_fail (factory->priv != NULL);
|
||||
|
||||
+ if (factory->priv->purge_displays_id != 0) {
|
||||
+ g_source_remove (factory->priv->purge_displays_id);
|
||||
+ factory->priv->purge_displays_id = 0;
|
||||
+ }
|
||||
+
|
||||
G_OBJECT_CLASS (gdm_display_factory_parent_class)->finalize (object);
|
||||
}
|
||||
diff --git a/daemon/gdm-display-factory.h b/daemon/gdm-display-factory.h
|
||||
index 6b30f83dc..1cffa1bd5 100644
|
||||
--- a/daemon/gdm-display-factory.h
|
||||
+++ b/daemon/gdm-display-factory.h
|
||||
@@ -37,34 +37,35 @@ G_BEGIN_DECLS
|
||||
|
||||
typedef struct GdmDisplayFactoryPrivate GdmDisplayFactoryPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObject parent;
|
||||
GdmDisplayFactoryPrivate *priv;
|
||||
} GdmDisplayFactory;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (*start) (GdmDisplayFactory *factory);
|
||||
gboolean (*stop) (GdmDisplayFactory *factory);
|
||||
} GdmDisplayFactoryClass;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDM_DISPLAY_FACTORY_ERROR_GENERAL
|
||||
} GdmDisplayFactoryError;
|
||||
|
||||
#define GDM_DISPLAY_FACTORY_ERROR gdm_display_factory_error_quark ()
|
||||
|
||||
GQuark gdm_display_factory_error_quark (void);
|
||||
GType gdm_display_factory_get_type (void);
|
||||
|
||||
gboolean gdm_display_factory_start (GdmDisplayFactory *manager);
|
||||
gboolean gdm_display_factory_stop (GdmDisplayFactory *manager);
|
||||
GdmDisplayStore * gdm_display_factory_get_display_store (GdmDisplayFactory *manager);
|
||||
+void gdm_display_factory_queue_purge_displays (GdmDisplayFactory *manager);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDM_DISPLAY_FACTORY_H */
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index ab7e12e91..1a9196ee1 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -222,107 +222,104 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
||||
"seat-id", "seat0",
|
||||
"allow-timed-login", FALSE,
|
||||
NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (! gdm_display_get_id (display, id, NULL)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
/* ref either held by store or not at all */
|
||||
g_object_unref (display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
int status;
|
||||
- GdmDisplayStore *store;
|
||||
int num;
|
||||
char *seat_id = NULL;
|
||||
char *session_type = NULL;
|
||||
gboolean is_initial = TRUE;
|
||||
gboolean is_local = TRUE;
|
||||
|
||||
num = -1;
|
||||
gdm_display_get_x11_display_number (display, &num, NULL);
|
||||
|
||||
- store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
-
|
||||
g_object_get (display,
|
||||
"seat-id", &seat_id,
|
||||
"is-initial", &is_initial,
|
||||
"is-local", &is_local,
|
||||
"session-type", &session_type,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
/* remove the display number from factory->priv->used_display_numbers
|
||||
so that it may be reused */
|
||||
if (num != -1) {
|
||||
g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
|
||||
}
|
||||
- gdm_display_store_remove (store, display);
|
||||
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
/* if this is a local display, do a full resync. Only
|
||||
* seats without displays will get created anyway. This
|
||||
* ensures we get a new login screen when the user logs out,
|
||||
* if there isn't one.
|
||||
*/
|
||||
if (is_local) {
|
||||
/* reset num failures */
|
||||
factory->priv->num_failures = 0;
|
||||
|
||||
gdm_local_display_factory_sync_seats (factory);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
/* leave the display number in factory->priv->used_display_numbers
|
||||
so that it doesn't get reused */
|
||||
- gdm_display_store_remove (store, display);
|
||||
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
/* Create a new equivalent display if it was static */
|
||||
if (is_local) {
|
||||
|
||||
factory->priv->num_failures++;
|
||||
|
||||
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
||||
/* oh shit */
|
||||
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
||||
} else {
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
if (g_strcmp0 (session_type, "wayland") == 0) {
|
||||
g_free (session_type);
|
||||
session_type = NULL;
|
||||
|
||||
/* workaround logind race for now
|
||||
* bug 1643874
|
||||
*/
|
||||
g_usleep (2 * G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
#endif
|
||||
create_display (factory, seat_id, session_type, is_initial);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
break;
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
break;
|
||||
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
|
||||
index 46a0d9ffa..5b5786c6f 100644
|
||||
--- a/daemon/gdm-xdmcp-display-factory.c
|
||||
+++ b/daemon/gdm-xdmcp-display-factory.c
|
||||
@@ -2039,93 +2039,90 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display,
|
||||
char *ip;
|
||||
ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
|
||||
|
||||
ip = NULL;
|
||||
gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
|
||||
g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
|
||||
ip ? ip : "(null)");
|
||||
g_free (ip);
|
||||
}
|
||||
|
||||
freeaddrinfo (ai_list);
|
||||
}
|
||||
|
||||
static void
|
||||
on_client_disconnected (GdmDisplay *display)
|
||||
{
|
||||
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
|
||||
return;
|
||||
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmXdmcpDisplayFactory *factory)
|
||||
{
|
||||
int status;
|
||||
- GdmDisplayStore *store;
|
||||
GdmLaunchEnvironment *launch_environment;
|
||||
GdmSession *session;
|
||||
GdmAddress *address;
|
||||
gint32 session_number;
|
||||
int display_number;
|
||||
|
||||
- store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
-
|
||||
launch_environment = NULL;
|
||||
g_object_get (display, "launch-environment", &launch_environment, NULL);
|
||||
|
||||
session = NULL;
|
||||
if (launch_environment != NULL) {
|
||||
session = gdm_launch_environment_get_session (launch_environment);
|
||||
}
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status);
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
g_object_get (display,
|
||||
"remote-address", &address,
|
||||
"x11-display-number", &display_number,
|
||||
"session-number", &session_number,
|
||||
NULL);
|
||||
gdm_xdmcp_send_alive (factory, address, display_number, session_number);
|
||||
|
||||
- gdm_display_store_remove (store, display);
|
||||
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
- gdm_display_store_remove (store, display);
|
||||
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
break;
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
if (session != NULL) {
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (session),
|
||||
G_CALLBACK (on_client_disconnected),
|
||||
display);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
break;
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
if (session != NULL) {
|
||||
g_signal_connect_object (G_OBJECT (session),
|
||||
"client-disconnected",
|
||||
G_CALLBACK (on_client_disconnected),
|
||||
display, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (G_OBJECT (session),
|
||||
"disconnected",
|
||||
G_CALLBACK (on_client_disconnected),
|
||||
display, G_CONNECT_SWAPPED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
|
||||
--
|
||||
2.27.0
|
||||
|
@ -54,7 +54,7 @@ index 403921d32..ab7e12e91 100644
|
||||
+ /* workaround logind race for now
|
||||
+ * bug 1643874
|
||||
+ */
|
||||
+ sleep (2);
|
||||
+ g_usleep (2 * G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
353
SOURCES/0001-manager-Don-t-leak-session-objects.patch
Normal file
353
SOURCES/0001-manager-Don-t-leak-session-objects.patch
Normal file
@ -0,0 +1,353 @@
|
||||
From de229615d80fd7c8a38ab5d5d7b30aa98f43721d Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Mon, 14 Sep 2020 16:20:09 -0400
|
||||
Subject: [PATCH 1/3] manager: Don't leak session objects
|
||||
|
||||
The first is from create_user_session_for display. Most callers don't
|
||||
check the return value, so it should just be void.
|
||||
|
||||
The user data associated with the session also isn't unlinked from the
|
||||
display when the display is finishing up, preventing the display and
|
||||
session object from getting freed.
|
||||
|
||||
This commit makes both changes.
|
||||
---
|
||||
daemon/gdm-manager.c | 17 +++++++++--------
|
||||
1 file changed, 9 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index bff602a07..738671679 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -94,63 +94,63 @@ struct GdmManagerPrivate
|
||||
#ifdef WITH_PLYMOUTH
|
||||
guint plymouth_is_running : 1;
|
||||
#endif
|
||||
guint did_automatic_login : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_XDMCP_ENABLED,
|
||||
PROP_SHOW_LOCAL_GREETER
|
||||
};
|
||||
|
||||
enum {
|
||||
DISPLAY_ADDED,
|
||||
DISPLAY_REMOVED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SESSION_RECORD_LOGIN,
|
||||
SESSION_RECORD_LOGOUT,
|
||||
SESSION_RECORD_FAILED,
|
||||
} SessionRecord;
|
||||
|
||||
static guint signals [LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void gdm_manager_class_init (GdmManagerClass *klass);
|
||||
static void gdm_manager_init (GdmManager *manager);
|
||||
static void gdm_manager_dispose (GObject *object);
|
||||
|
||||
-static GdmSession *create_user_session_for_display (GdmManager *manager,
|
||||
- GdmDisplay *display,
|
||||
- uid_t allowed_user);
|
||||
+static void create_user_session_for_display (GdmManager *manager,
|
||||
+ GdmDisplay *display,
|
||||
+ uid_t allowed_user);
|
||||
static void start_user_session (GdmManager *manager,
|
||||
StartUserSessionOperation *operation);
|
||||
static void clean_user_session (GdmSession *session);
|
||||
|
||||
static gpointer manager_object = NULL;
|
||||
|
||||
static void manager_interface_init (GdmDBusManagerIface *interface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GdmManager,
|
||||
gdm_manager,
|
||||
GDM_DBUS_TYPE_MANAGER_SKELETON,
|
||||
G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_MANAGER,
|
||||
manager_interface_init));
|
||||
|
||||
#ifdef WITH_PLYMOUTH
|
||||
static gboolean
|
||||
plymouth_is_running (void)
|
||||
{
|
||||
int status;
|
||||
gboolean res;
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
res = g_spawn_command_line_sync ("/bin/plymouth --ping",
|
||||
NULL, NULL, &status, &error);
|
||||
if (! res) {
|
||||
g_debug ("Could not ping plymouth: %s", error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1343,61 +1343,62 @@ get_automatic_login_details (GdmManager *manager,
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_username_for_greeter_display (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
if (doing_initial_setup) {
|
||||
return INITIAL_SETUP_USERNAME;
|
||||
} else {
|
||||
return GDM_USERNAME;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_automatic_login_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
GdmSession *session;
|
||||
char *display_session_type = NULL;
|
||||
|
||||
/* 0 is root user; since the daemon talks to the session object
|
||||
* directly, itself, for automatic login
|
||||
*/
|
||||
- session = create_user_session_for_display (manager, display, 0);
|
||||
+ create_user_session_for_display (manager, display, 0);
|
||||
+ session = get_user_session_for_display (display);
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"session-type", &display_session_type,
|
||||
NULL);
|
||||
|
||||
g_object_set (G_OBJECT (session),
|
||||
"display-is-initial", FALSE,
|
||||
NULL);
|
||||
|
||||
g_debug ("GdmManager: Starting automatic login conversation");
|
||||
gdm_session_start_conversation (session, "gdm-autologin");
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_chooser_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
const char *allowed_user;
|
||||
struct passwd *passwd_entry;
|
||||
|
||||
allowed_user = get_username_for_greeter_display (manager, display);
|
||||
|
||||
if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
|
||||
g_warning ("GdmManager: couldn't look up username %s",
|
||||
allowed_user);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1549,60 +1550,62 @@ on_display_status_changed (GdmDisplay *display,
|
||||
"session-type", &session_type,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
|
||||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
|
||||
char *session_class;
|
||||
|
||||
g_object_get (display,
|
||||
"session-class", &session_class,
|
||||
NULL);
|
||||
if (g_strcmp0 (session_class, "greeter") == 0)
|
||||
set_up_session (manager, display);
|
||||
g_free (session_class);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
#ifdef WITH_PLYMOUTH
|
||||
if (quit_plymouth) {
|
||||
plymouth_quit_without_transition ();
|
||||
manager->priv->plymouth_is_running = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
+ g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
+
|
||||
if (display == manager->priv->automatic_login_display) {
|
||||
g_clear_weak_pointer (&manager->priv->automatic_login_display);
|
||||
|
||||
manager->priv->did_automatic_login = TRUE;
|
||||
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) {
|
||||
/* we're going to fall back to X11, so try to autologin again
|
||||
*/
|
||||
manager->priv->did_automatic_login = FALSE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
char *id;
|
||||
|
||||
gdm_display_get_id (display, &id, NULL);
|
||||
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
||||
g_free (id);
|
||||
@@ -2292,61 +2295,61 @@ on_session_reauthentication_started (GdmSession *session,
|
||||
int pid_of_caller,
|
||||
const char *address,
|
||||
GdmManager *manager)
|
||||
{
|
||||
GDBusMethodInvocation *invocation;
|
||||
gpointer source_tag;
|
||||
|
||||
g_debug ("GdmManager: reauthentication started");
|
||||
|
||||
source_tag = GINT_TO_POINTER (pid_of_caller);
|
||||
|
||||
invocation = g_hash_table_lookup (manager->priv->open_reauthentication_requests,
|
||||
source_tag);
|
||||
|
||||
if (invocation != NULL) {
|
||||
g_hash_table_steal (manager->priv->open_reauthentication_requests,
|
||||
source_tag);
|
||||
gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
|
||||
invocation,
|
||||
address);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clean_user_session (GdmSession *session)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (session), "gdm-display", NULL);
|
||||
g_object_unref (session);
|
||||
}
|
||||
|
||||
-static GdmSession *
|
||||
+static void
|
||||
create_user_session_for_display (GdmManager *manager,
|
||||
GdmDisplay *display,
|
||||
uid_t allowed_user)
|
||||
{
|
||||
GdmSession *session;
|
||||
gboolean display_is_local = FALSE;
|
||||
char *display_name = NULL;
|
||||
char *display_device = NULL;
|
||||
char *remote_hostname = NULL;
|
||||
char *display_auth_file = NULL;
|
||||
char *display_seat_id = NULL;
|
||||
char *display_id = NULL;
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
char *display_session_type = NULL;
|
||||
gboolean greeter_is_wayland;
|
||||
#endif
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"id", &display_id,
|
||||
"x11-display-name", &display_name,
|
||||
"is-local", &display_is_local,
|
||||
"remote-hostname", &remote_hostname,
|
||||
"x11-authority-file", &display_auth_file,
|
||||
"seat-id", &display_seat_id,
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
"session-type", &display_session_type,
|
||||
#endif
|
||||
NULL);
|
||||
display_device = get_display_device (manager, display);
|
||||
|
||||
@@ -2402,70 +2405,68 @@ create_user_session_for_display (GdmManager *manager,
|
||||
"conversation-stopped",
|
||||
G_CALLBACK (on_session_conversation_stopped),
|
||||
manager);
|
||||
g_signal_connect (session,
|
||||
"authentication-failed",
|
||||
G_CALLBACK (on_session_authentication_failed),
|
||||
manager);
|
||||
g_signal_connect (session,
|
||||
"session-opened",
|
||||
G_CALLBACK (on_user_session_opened),
|
||||
manager);
|
||||
g_signal_connect (session,
|
||||
"session-started",
|
||||
G_CALLBACK (on_user_session_started),
|
||||
manager);
|
||||
g_signal_connect (session,
|
||||
"session-start-failed",
|
||||
G_CALLBACK (on_session_start_failed),
|
||||
manager);
|
||||
g_signal_connect (session,
|
||||
"session-exited",
|
||||
G_CALLBACK (on_user_session_exited),
|
||||
manager);
|
||||
g_signal_connect (session,
|
||||
"session-died",
|
||||
G_CALLBACK (on_user_session_died),
|
||||
manager);
|
||||
g_object_set_data (G_OBJECT (session), "gdm-display", display);
|
||||
g_object_set_data_full (G_OBJECT (display),
|
||||
"gdm-user-session",
|
||||
- g_object_ref (session),
|
||||
+ session,
|
||||
(GDestroyNotify)
|
||||
clean_user_session);
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
greeter_is_wayland = g_strcmp0 (display_session_type, "wayland") == 0;
|
||||
g_object_set (G_OBJECT (session), "ignore-wayland", !greeter_is_wayland, NULL);
|
||||
#endif
|
||||
-
|
||||
- return session;
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_added (GdmDisplayStore *display_store,
|
||||
const char *id,
|
||||
GdmManager *manager)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_lookup (display_store, id);
|
||||
|
||||
if (display != NULL) {
|
||||
g_dbus_object_manager_server_export (manager->priv->object_manager,
|
||||
gdm_display_get_object_skeleton (display));
|
||||
|
||||
g_signal_connect (display, "notify::status",
|
||||
G_CALLBACK (on_display_status_changed),
|
||||
manager);
|
||||
g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
|
||||
}
|
||||
}
|
||||
|
||||
GQuark
|
||||
gdm_manager_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
if (ret == 0) {
|
||||
ret = g_quark_from_static_string ("gdm_manager_error");
|
||||
}
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -15,10 +15,10 @@ treated as autologin sessions.
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 2118c5834..b2d0578f5 100644
|
||||
index 1943d89e4..72d44b006 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1841,61 +1841,62 @@ on_start_user_session (StartUserSessionOperation *operation)
|
||||
@@ -1838,61 +1838,62 @@ on_start_user_session (StartUserSessionOperation *operation)
|
||||
NULL);
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
@ -52,23 +52,16 @@ index 2118c5834..b2d0578f5 100644
|
||||
- if (g_strcmp0 (operation->service_name, "gdm-autologin") == 0) {
|
||||
+ if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
+ !gdm_session_client_is_connected (operation->session)) {
|
||||
gboolean was_initial = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display), "is-initial", &was_initial, NULL);
|
||||
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
|
||||
should_be_initial = was_initial;
|
||||
}
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
session_id,
|
||||
should_be_initial);
|
||||
session_id);
|
||||
}
|
||||
|
||||
if (starting_user_session_right_away) {
|
||||
@ -82,6 +75,13 @@ index 2118c5834..b2d0578f5 100644
|
||||
static void
|
||||
queue_start_user_session (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
StartUserSessionOperation *operation;
|
||||
|
||||
operation = g_slice_new0 (StartUserSessionOperation);
|
||||
operation->manager = manager;
|
||||
operation->session = g_object_ref (session);
|
||||
--
|
||||
2.21.0
|
||||
2.26.0
|
||||
|
||||
|
@ -1,198 +0,0 @@
|
||||
From 4b2db2cf52be75e2eec4aa29f8ee082392ded410 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 1 Nov 2018 13:03:37 -0400
|
||||
Subject: [PATCH] manager: ensure is-initial is transfered to autologin display
|
||||
|
||||
At the moment, we don't handle transferring the is-initial property to
|
||||
the autologin display.
|
||||
|
||||
That prevents autologin from working if wayland fails and X falls back,
|
||||
since autologin currently requires an initial display.
|
||||
|
||||
This commit makes sure we properly transfer is-initial from greeter to
|
||||
user display.
|
||||
---
|
||||
daemon/gdm-manager.c | 14 ++++++++++++--
|
||||
1 file changed, 12 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 1943d89e4..2118c5834 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1740,90 +1740,93 @@ start_user_session (GdmManager *manager,
|
||||
|
||||
g_object_get (G_OBJECT (display), "is-connected", &is_connected, NULL);
|
||||
|
||||
if (is_connected) {
|
||||
auth_file = NULL;
|
||||
username = gdm_session_get_username (operation->session);
|
||||
gdm_display_add_user_authorization (display,
|
||||
username,
|
||||
&auth_file,
|
||||
NULL);
|
||||
|
||||
g_assert (auth_file != NULL);
|
||||
|
||||
g_object_set (operation->session,
|
||||
"user-x11-authority-file", auth_file,
|
||||
NULL);
|
||||
|
||||
g_free (auth_file);
|
||||
}
|
||||
}
|
||||
|
||||
gdm_session_start_session (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
destroy_start_user_session_operation (operation);
|
||||
}
|
||||
|
||||
static void
|
||||
create_display_for_user_session (GdmManager *self,
|
||||
GdmSession *session,
|
||||
- const char *session_id)
|
||||
+ const char *session_id,
|
||||
+ gboolean is_initial)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
/* at the moment we only create GdmLocalDisplay objects on seat0 */
|
||||
const char *seat_id = "seat0";
|
||||
|
||||
display = gdm_local_display_new ();
|
||||
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"seat-id", seat_id,
|
||||
"session-id", session_id,
|
||||
+ "is-initial", is_initial,
|
||||
NULL);
|
||||
gdm_display_store_add (self->priv->display_store,
|
||||
display);
|
||||
g_object_set_data (G_OBJECT (session), "gdm-display", display);
|
||||
g_object_set_data_full (G_OBJECT (display),
|
||||
"gdm-user-session",
|
||||
g_object_ref (session),
|
||||
(GDestroyNotify)
|
||||
clean_user_session);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_start_user_session (StartUserSessionOperation *operation)
|
||||
{
|
||||
GdmManager *self = operation->manager;
|
||||
gboolean migrated;
|
||||
gboolean fail_if_already_switched = TRUE;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
+ gboolean should_be_initial = FALSE;
|
||||
gboolean starting_user_session_right_away = TRUE;
|
||||
GdmDisplay *display;
|
||||
const char *session_id;
|
||||
|
||||
g_debug ("GdmManager: start or jump to session");
|
||||
|
||||
/* If there's already a session running, jump to it.
|
||||
* If the only session running is the one we just opened,
|
||||
* start a session on it.
|
||||
*/
|
||||
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
|
||||
|
||||
g_debug ("GdmManager: migrated: %d", migrated);
|
||||
if (migrated) {
|
||||
/* We don't stop the manager here because
|
||||
when Xorg exits it switches to the VT it was
|
||||
started from. That interferes with fast
|
||||
user switching. */
|
||||
gdm_session_reset (operation->session);
|
||||
destroy_start_user_session_operation (operation);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display = get_display_for_user_session (operation->session);
|
||||
|
||||
g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
|
||||
|
||||
session_id = gdm_session_get_conversation_session_id (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
@@ -1839,70 +1842,77 @@ on_start_user_session (StartUserSessionOperation *operation)
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
|
||||
g_object_ref (display);
|
||||
if (doing_initial_setup) {
|
||||
g_debug ("GdmManager: closing down initial setup display");
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
|
||||
/* We can't start the user session until the finished display
|
||||
* starts to respawn (since starting an X server and bringing
|
||||
* one down at the same time is a no go)
|
||||
*/
|
||||
g_assert (self->priv->initial_login_operation == NULL);
|
||||
self->priv->initial_login_operation = operation;
|
||||
starting_user_session_right_away = FALSE;
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
if (g_strcmp0 (operation->service_name, "gdm-autologin") == 0) {
|
||||
+ gboolean was_initial = FALSE;
|
||||
+
|
||||
+ g_object_get (G_OBJECT (display), "is-initial", &was_initial, NULL);
|
||||
+
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
+
|
||||
+ should_be_initial = was_initial;
|
||||
}
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
- session_id);
|
||||
+ session_id,
|
||||
+ should_be_initial);
|
||||
}
|
||||
|
||||
if (starting_user_session_right_away) {
|
||||
start_user_session (operation->manager, operation);
|
||||
}
|
||||
|
||||
out:
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_start_user_session (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
StartUserSessionOperation *operation;
|
||||
|
||||
operation = g_slice_new0 (StartUserSessionOperation);
|
||||
operation->manager = manager;
|
||||
operation->session = g_object_ref (session);
|
||||
operation->service_name = g_strdup (service_name);
|
||||
|
||||
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
|
||||
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
|
||||
}
|
||||
|
||||
static void
|
||||
start_user_session_if_ready (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
--
|
||||
2.19.1
|
||||
|
@ -0,0 +1,683 @@
|
||||
From 3864af1ea06d2125c1b1f5afa6fc12caa833980a Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 10 Dec 2020 15:14:20 -0500
|
||||
Subject: [PATCH] session-worker: Don't switch back VTs until session is fully
|
||||
exited
|
||||
|
||||
There's a race condition on shutdown where the session worker is
|
||||
switching VTs back to the initial VT at the same time as the session
|
||||
exit is being processed.
|
||||
|
||||
This means that manager may try to start a login screen (because of
|
||||
the VT switch) when autologin is enabled when there shouldn't be a
|
||||
login screen.
|
||||
|
||||
This commit makes sure both the PostSession script, and session-exited
|
||||
signal emission are complete before initiating the VT switch back
|
||||
to the initial VT.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gdm/-/issues/660
|
||||
---
|
||||
daemon/Makefile.am | 12 +++++
|
||||
daemon/gdm-session-worker.c | 93 +++++++++++++++++++++++++++------
|
||||
daemon/org.freedesktop.DBus.xml | 12 +++++
|
||||
3 files changed, 101 insertions(+), 16 deletions(-)
|
||||
create mode 100644 daemon/org.freedesktop.DBus.xml
|
||||
|
||||
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
|
||||
index 86a8ee32f..b323f6455 100644
|
||||
--- a/daemon/Makefile.am
|
||||
+++ b/daemon/Makefile.am
|
||||
@@ -7,83 +7,92 @@ AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/pam-extensions \
|
||||
-I$(top_builddir)/common \
|
||||
-DBINDIR=\"$(bindir)\" \
|
||||
-DDATADIR=\"$(datadir)\" \
|
||||
-DDMCONFDIR=\"$(dmconfdir)\" \
|
||||
-DGDMCONFDIR=\"$(gdmconfdir)\" \
|
||||
-DLIBDIR=\"$(libdir)\" \
|
||||
-DLIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DLOCALSTATEDIR=\"$(localstatedir)\" \
|
||||
-DLOGDIR=\"$(logdir)\" \
|
||||
-DSBINDIR=\"$(sbindir)\" \
|
||||
-DSYSCONFDIR=\"$(sysconfdir)\" \
|
||||
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
|
||||
-DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \
|
||||
-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
|
||||
-DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \
|
||||
-DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
|
||||
-DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
|
||||
$(DISABLE_DEPRECATED_CFLAGS) \
|
||||
$(DAEMON_CFLAGS) \
|
||||
$(XLIB_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(DEBUG_CFLAGS) \
|
||||
$(SYSTEMD_CFLAGS) \
|
||||
$(JOURNALD_CFLAGS) \
|
||||
$(LIBSELINUX_CFLAGS) \
|
||||
-DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \
|
||||
$(NULL)
|
||||
|
||||
BUILT_SOURCES = \
|
||||
+ gdm-dbus-glue.h \
|
||||
gdm-display-glue.h \
|
||||
gdm-manager-glue.h \
|
||||
gdm-local-display-glue.h \
|
||||
gdm-local-display-factory-glue.h \
|
||||
gdm-session-glue.h \
|
||||
gdm-session-worker-glue.h \
|
||||
gdm-session-enum-types.h \
|
||||
gdm-session-worker-enum-types.h \
|
||||
com.redhat.AccountsServiceUser.System.h \
|
||||
$(NULL)
|
||||
|
||||
gdm-session-enum-types.h: gdm-session-enum-types.h.in gdm-session.h
|
||||
$(AM_V_GEN) glib-mkenums --template $^ > $@
|
||||
|
||||
gdm-session-enum-types.c: gdm-session-enum-types.c.in gdm-session.h
|
||||
$(AM_V_GEN) glib-mkenums --template $^ > $@
|
||||
|
||||
gdm-session-worker-enum-types.h: gdm-session-worker-enum-types.h.in gdm-session-worker.h
|
||||
$(AM_V_GEN) glib-mkenums --template $^ > $@
|
||||
|
||||
gdm-session-worker-enum-types.c: gdm-session-worker-enum-types.c.in gdm-session-worker.h
|
||||
$(AM_V_GEN) glib-mkenums --template $^ > $@
|
||||
|
||||
+gdm-dbus-glue.c gdm-dbus-glue.h: org.freedesktop.DBus.xml Makefile.am
|
||||
+ $(AM_V_GEN)gdbus-codegen \
|
||||
+ --c-namespace=GdmDBus \
|
||||
+ --interface-prefix=org.freedesktop.DBus \
|
||||
+ --generate-c-code=gdm-dbus-glue \
|
||||
+ --c-generate-autocleanup=all \
|
||||
+ $(srcdir)/org.freedesktop.DBus.xml
|
||||
+
|
||||
gdm-display-glue.c gdm-display-glue.h: gdm-display.xml Makefile.am
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--c-namespace=GdmDBus \
|
||||
--interface-prefix=org.gnome.DisplayManager \
|
||||
--generate-c-code=gdm-display-glue \
|
||||
$(srcdir)/gdm-display.xml
|
||||
|
||||
gdm-local-display-glue.c gdm-local-display-glue.h: gdm-local-display.xml Makefile.am
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--c-namespace=GdmDBus \
|
||||
--interface-prefix=org.gnome.DisplayManager \
|
||||
--generate-c-code=gdm-local-display-glue \
|
||||
$(srcdir)/gdm-local-display.xml
|
||||
|
||||
gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-display-factory.xml Makefile.am
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--c-namespace=GdmDBus \
|
||||
--interface-prefix=org.gnome.DisplayManager \
|
||||
--generate-c-code=gdm-local-display-factory-glue \
|
||||
$(srcdir)/gdm-local-display-factory.xml
|
||||
|
||||
gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
--c-namespace=GdmDBus \
|
||||
--interface-prefix=org.gnome.DisplayManager \
|
||||
--generate-c-code=gdm-manager-glue \
|
||||
$(srcdir)/gdm-manager.xml
|
||||
|
||||
gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
@@ -130,60 +139,62 @@ libexec_PROGRAMS = \
|
||||
gdm-wayland-session \
|
||||
gdm-x-session \
|
||||
$(NULL)
|
||||
|
||||
gdm_session_worker_SOURCES = \
|
||||
session-worker-main.c \
|
||||
com.redhat.AccountsServiceUser.System.h \
|
||||
com.redhat.AccountsServiceUser.System.c \
|
||||
gdm-session.c \
|
||||
gdm-session.h \
|
||||
gdm-session-settings.h \
|
||||
gdm-session-settings.c \
|
||||
gdm-session-auditor.h \
|
||||
gdm-session-auditor.c \
|
||||
gdm-session-record.c \
|
||||
gdm-session-record.h \
|
||||
gdm-session-worker.h \
|
||||
gdm-session-worker.c \
|
||||
gdm-session-worker-job.c \
|
||||
gdm-session-worker-common.c \
|
||||
gdm-session-worker-common.h \
|
||||
gdm-dbus-util.c \
|
||||
gdm-dbus-util.h \
|
||||
$(NULL)
|
||||
|
||||
if SUPPORTS_PAM_EXTENSIONS
|
||||
gdm_session_worker_SOURCES += $(top_srcdir)/pam-extensions/gdm-pam-extensions.h
|
||||
endif
|
||||
|
||||
nodist_gdm_session_worker_SOURCES = \
|
||||
+ gdm-dbus-glue.h \
|
||||
+ gdm-dbus-glue.c \
|
||||
gdm-session-glue.h \
|
||||
gdm-session-glue.c \
|
||||
gdm-session-worker-glue.c \
|
||||
gdm-session-worker-glue.h \
|
||||
gdm-session-enum-types.c \
|
||||
gdm-session-worker-enum-types.c \
|
||||
gdm-session-enum-types.h \
|
||||
$(NULL)
|
||||
|
||||
gdm_wayland_session_LDADD = \
|
||||
$(top_builddir)/common/libgdmcommon.la \
|
||||
$(GTK_LIBS) \
|
||||
$(COMMON_LIBS) \
|
||||
$(SYSTEMD_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
gdm_wayland_session_SOURCES = \
|
||||
gdm-manager-glue.h \
|
||||
gdm-manager-glue.c \
|
||||
gdm-wayland-session.c \
|
||||
$(NULL)
|
||||
|
||||
gdm_x_session_LDADD = \
|
||||
$(top_builddir)/common/libgdmcommon.la \
|
||||
$(GTK_LIBS) \
|
||||
$(COMMON_LIBS) \
|
||||
$(SYSTEMD_LIBS) \
|
||||
$(XLIB_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
@@ -271,50 +282,51 @@ nodist_gdm_SOURCES = \
|
||||
|
||||
XDMCP_SOURCES = \
|
||||
gdm-xdmcp-display-factory.c \
|
||||
gdm-xdmcp-display-factory.h \
|
||||
gdm-xdmcp-display.c \
|
||||
gdm-xdmcp-display.h \
|
||||
gdm-xdmcp-chooser-display.c \
|
||||
gdm-xdmcp-chooser-display.h \
|
||||
$(NULL)
|
||||
|
||||
if XDMCP_SUPPORT
|
||||
gdm_SOURCES += $(XDMCP_SOURCES)
|
||||
endif
|
||||
|
||||
EXTRA_gdm_SOURCES = \
|
||||
$(XDMCP_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
gdm_LDADD = \
|
||||
$(top_builddir)/common/libgdmcommon.la \
|
||||
$(XLIB_LIBS) \
|
||||
$(DAEMON_LIBS) \
|
||||
$(XDMCP_LIBS) \
|
||||
$(LIBWRAP_LIBS) \
|
||||
$(SYSTEMD_LIBS) \
|
||||
$(JOURNALD_LIBS) \
|
||||
$(EXTRA_DAEMON_LIBS) \
|
||||
$(NULL)
|
||||
|
||||
CLEANFILES = \
|
||||
+ gdm-dbus-glue.c \
|
||||
gdm-display-glue.c \
|
||||
gdm-local-display-factory-glue.c \
|
||||
gdm-manager-glue.c \
|
||||
gdm-session-glue.c \
|
||||
gdm-session-worker-glue.c \
|
||||
gdm-session-enum-types.c \
|
||||
gdm-local-display-glue.c \
|
||||
$(BUILT_SOURCES) \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
gdm-manager.xml \
|
||||
gdm-session-worker.xml \
|
||||
gdm-session.xml \
|
||||
gdm-display.xml \
|
||||
gdm-local-display.xml \
|
||||
gdm-local-display-factory.xml \
|
||||
gdm-session-enum-types.c.in \
|
||||
gdm-session-enum-types.h.in \
|
||||
$(NULL)
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index 42c415837..c1b2c1765 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -39,60 +39,61 @@
|
||||
|
||||
#ifdef HAVE_LOGINCAP
|
||||
#include <login_cap.h>
|
||||
#endif
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <X11/Xauth.h>
|
||||
|
||||
#include <systemd/sd-daemon.h>
|
||||
|
||||
#ifdef ENABLE_SYSTEMD_JOURNAL
|
||||
#include <systemd/sd-journal.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
#include <selinux/selinux.h>
|
||||
#endif /* HAVE_SELINUX */
|
||||
|
||||
#include "gdm-common.h"
|
||||
#include "gdm-log.h"
|
||||
|
||||
#ifdef SUPPORTS_PAM_EXTENSIONS
|
||||
#include "gdm-pam-extensions.h"
|
||||
#endif
|
||||
|
||||
+#include "gdm-dbus-glue.h"
|
||||
#include "gdm-session-worker.h"
|
||||
#include "gdm-session-glue.h"
|
||||
#include "gdm-session.h"
|
||||
|
||||
#if defined (HAVE_ADT)
|
||||
#include "gdm-session-solaris-auditor.h"
|
||||
#elif defined (HAVE_LIBAUDIT)
|
||||
#include "gdm-session-linux-auditor.h"
|
||||
#else
|
||||
#include "gdm-session-auditor.h"
|
||||
#endif
|
||||
|
||||
#include "gdm-session-settings.h"
|
||||
|
||||
#define GDM_SESSION_WORKER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerPrivate))
|
||||
|
||||
#define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session"
|
||||
#define GDM_SESSION_DBUS_NAME "org.gnome.DisplayManager.Session"
|
||||
#define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
|
||||
|
||||
#define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker"
|
||||
|
||||
#ifndef GDM_PASSWD_AUXILLARY_BUFFER_SIZE
|
||||
#define GDM_PASSWD_AUXILLARY_BUFFER_SIZE 1024
|
||||
#endif
|
||||
|
||||
#ifndef GDM_SESSION_DEFAULT_PATH
|
||||
#define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin"
|
||||
#endif
|
||||
|
||||
@@ -1028,72 +1029,60 @@ gdm_session_worker_set_state (GdmSessionWorker *worker,
|
||||
|
||||
static void
|
||||
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
|
||||
int status)
|
||||
{
|
||||
g_debug ("GdmSessionWorker: uninitializing PAM");
|
||||
|
||||
if (worker->priv->pam_handle == NULL)
|
||||
return;
|
||||
|
||||
gdm_session_worker_get_username (worker, NULL);
|
||||
|
||||
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
|
||||
pam_close_session (worker->priv->pam_handle, 0);
|
||||
gdm_session_auditor_report_logout (worker->priv->auditor);
|
||||
} else {
|
||||
gdm_session_auditor_report_login_failure (worker->priv->auditor,
|
||||
status,
|
||||
pam_strerror (worker->priv->pam_handle, status));
|
||||
}
|
||||
|
||||
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) {
|
||||
pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED);
|
||||
}
|
||||
|
||||
pam_end (worker->priv->pam_handle, status);
|
||||
worker->priv->pam_handle = NULL;
|
||||
|
||||
gdm_session_worker_stop_auditor (worker);
|
||||
|
||||
- /* If user-display-server is not enabled the login_vt is always
|
||||
- * identical to the session_vt. So in that case we never need to
|
||||
- * do a VT switch. */
|
||||
-#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
- if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
|
||||
- /* Switch to the login VT if we are not the login screen. */
|
||||
- if (worker->priv->session_vt != GDM_INITIAL_VT) {
|
||||
- jump_to_vt (worker, GDM_INITIAL_VT);
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
-
|
||||
worker->priv->session_vt = 0;
|
||||
|
||||
g_debug ("GdmSessionWorker: state NONE");
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE);
|
||||
}
|
||||
|
||||
static char *
|
||||
_get_tty_for_pam (const char *x11_display_name,
|
||||
const char *display_device)
|
||||
{
|
||||
#ifdef __sun
|
||||
return g_strdup (display_device);
|
||||
#else
|
||||
return g_strdup (x11_display_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef PAM_XAUTHDATA
|
||||
static struct pam_xauth_data *
|
||||
_get_xauth_for_pam (const char *x11_authority_file)
|
||||
{
|
||||
FILE *fh;
|
||||
Xauth *auth = NULL;
|
||||
struct pam_xauth_data *retval = NULL;
|
||||
gsize len = sizeof (*retval) + 1;
|
||||
|
||||
fh = fopen (x11_authority_file, "r");
|
||||
if (fh) {
|
||||
auth = XauReadAuth (fh);
|
||||
fclose (fh);
|
||||
@@ -1752,86 +1741,155 @@ gdm_session_worker_accredit_user (GdmSessionWorker *worker,
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCREDITED);
|
||||
} else {
|
||||
gdm_session_worker_uninitialize_pam (worker, error_code);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char * const *
|
||||
gdm_session_worker_get_environment (GdmSessionWorker *worker)
|
||||
{
|
||||
return (const char * const *) pam_getenvlist (worker->priv->pam_handle);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
run_script (GdmSessionWorker *worker,
|
||||
const char *dir)
|
||||
{
|
||||
/* scripts are for non-program sessions only */
|
||||
if (worker->priv->is_program_session) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return gdm_run_script (dir,
|
||||
worker->priv->username,
|
||||
worker->priv->x11_display_name,
|
||||
worker->priv->display_is_local? NULL : worker->priv->hostname,
|
||||
worker->priv->x11_authority_file);
|
||||
}
|
||||
|
||||
+static void
|
||||
+wait_until_dbus_signal_emission_to_manager_finishes (GdmSessionWorker *worker)
|
||||
+{
|
||||
+ g_autoptr (GdmDBusPeer) peer_proxy = NULL;
|
||||
+ g_autoptr (GError) error = NULL;
|
||||
+ gboolean pinged;
|
||||
+
|
||||
+ peer_proxy = gdm_dbus_peer_proxy_new_sync (worker->priv->connection,
|
||||
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
|
||||
+ NULL,
|
||||
+ "/org/freedesktop/DBus",
|
||||
+ NULL,
|
||||
+ &error);
|
||||
+
|
||||
+ if (peer_proxy == NULL) {
|
||||
+ g_debug ("GdmSessionWorker: could not create peer proxy to daemon: %s",
|
||||
+ error->message);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ pinged = gdm_dbus_peer_call_ping_sync (peer_proxy, NULL, &error);
|
||||
+
|
||||
+ if (!pinged) {
|
||||
+ g_debug ("GdmSessionWorker: could not ping daemon: %s",
|
||||
+ error->message);
|
||||
+ return;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+jump_back_to_initial_vt (GdmSessionWorker *worker)
|
||||
+{
|
||||
+ if (worker->priv->session_vt == 0)
|
||||
+ return;
|
||||
+
|
||||
+ if (worker->priv->session_vt == GDM_INITIAL_VT)
|
||||
+ return;
|
||||
+
|
||||
+ if (g_strcmp0 (worker->priv->display_seat_id, "seat0") != 0)
|
||||
+ return;
|
||||
+
|
||||
+#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
+ jump_to_vt (worker, GDM_INITIAL_VT);
|
||||
+ worker->priv->session_vt = 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static void
|
||||
session_worker_child_watch (GPid pid,
|
||||
int status,
|
||||
GdmSessionWorker *worker)
|
||||
{
|
||||
g_debug ("GdmSessionWorker: child (pid:%d) done (%s:%d)",
|
||||
(int) pid,
|
||||
WIFEXITED (status) ? "status"
|
||||
: WIFSIGNALED (status) ? "signal"
|
||||
: "unknown",
|
||||
WIFEXITED (status) ? WEXITSTATUS (status)
|
||||
: WIFSIGNALED (status) ? WTERMSIG (status)
|
||||
: -1);
|
||||
|
||||
-
|
||||
gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
|
||||
|
||||
+ worker->priv->child_pid = -1;
|
||||
+ worker->priv->child_watch_id = 0;
|
||||
+ run_script (worker, GDMCONFDIR "/PostSession");
|
||||
+
|
||||
gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker),
|
||||
worker->priv->service,
|
||||
status);
|
||||
|
||||
killpg (pid, SIGHUP);
|
||||
|
||||
- worker->priv->child_pid = -1;
|
||||
- worker->priv->child_watch_id = 0;
|
||||
- run_script (worker, GDMCONFDIR "/PostSession");
|
||||
+ /* FIXME: It's important to give the manager an opportunity to process the
|
||||
+ * session-exited emission above before switching VTs.
|
||||
+ *
|
||||
+ * This is because switching VTs makes the manager try to put a login screen
|
||||
+ * up on VT 1, but it may actually want to try to auto login again in response
|
||||
+ * to session-exited.
|
||||
+ *
|
||||
+ * This function just does a manager roundtrip over the bus to make sure the
|
||||
+ * signal has been dispatched before jumping.
|
||||
+ *
|
||||
+ * Ultimately, we may want to improve the manager<->worker interface.
|
||||
+ *
|
||||
+ * See:
|
||||
+ *
|
||||
+ * https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/123
|
||||
+ *
|
||||
+ * for some ideas and more discussion.
|
||||
+ *
|
||||
+ */
|
||||
+ wait_until_dbus_signal_emission_to_manager_finishes (worker);
|
||||
+
|
||||
+ jump_back_to_initial_vt (worker);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_watch_child (GdmSessionWorker *worker)
|
||||
{
|
||||
g_debug ("GdmSession worker: watching pid %d", worker->priv->child_pid);
|
||||
worker->priv->child_watch_id = g_child_watch_add (worker->priv->child_pid,
|
||||
(GChildWatchFunc)session_worker_child_watch,
|
||||
worker);
|
||||
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_is_loggable_file (const char* filename)
|
||||
{
|
||||
struct stat file_info;
|
||||
|
||||
if (g_lstat (filename, &file_info) < 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
rotate_logs (const char *path,
|
||||
guint n_copies)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -2401,60 +2459,61 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
|
||||
|
||||
flags = 0;
|
||||
|
||||
if (worker->priv->is_program_session) {
|
||||
flags |= PAM_SILENT;
|
||||
}
|
||||
|
||||
error_code = pam_open_session (worker->priv->pam_handle, flags);
|
||||
|
||||
if (error_code != PAM_SUCCESS) {
|
||||
g_set_error (error,
|
||||
GDM_SESSION_WORKER_ERROR,
|
||||
GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
|
||||
"%s", pam_strerror (worker->priv->pam_handle, error_code));
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_debug ("GdmSessionWorker: state SESSION_OPENED");
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_OPENED);
|
||||
|
||||
session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
|
||||
|
||||
if (session_id != NULL) {
|
||||
g_free (worker->priv->session_id);
|
||||
worker->priv->session_id = session_id;
|
||||
}
|
||||
|
||||
out:
|
||||
if (error_code != PAM_SUCCESS) {
|
||||
gdm_session_worker_uninitialize_pam (worker, error_code);
|
||||
+ worker->priv->session_vt = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gdm_session_worker_get_username (worker, NULL);
|
||||
gdm_session_auditor_report_login (worker->priv->auditor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_set_server_address (GdmSessionWorker *worker,
|
||||
const char *address)
|
||||
{
|
||||
g_free (worker->priv->server_address);
|
||||
worker->priv->server_address = g_strdup (address);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_set_is_reauth_session (GdmSessionWorker *worker,
|
||||
gboolean is_reauth_session)
|
||||
{
|
||||
worker->priv->is_reauth_session = is_reauth_session;
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
@@ -3565,60 +3624,62 @@ gdm_session_worker_unwatch_child (GdmSessionWorker *worker)
|
||||
return;
|
||||
|
||||
g_source_remove (worker->priv->child_watch_id);
|
||||
worker->priv->child_watch_id = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gdm_session_worker_finalize (GObject *object)
|
||||
{
|
||||
GdmSessionWorker *worker;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GDM_IS_SESSION_WORKER (object));
|
||||
|
||||
worker = GDM_SESSION_WORKER (object);
|
||||
|
||||
g_return_if_fail (worker->priv != NULL);
|
||||
|
||||
gdm_session_worker_unwatch_child (worker);
|
||||
|
||||
if (worker->priv->child_pid > 0) {
|
||||
gdm_signal_pid (worker->priv->child_pid, SIGTERM);
|
||||
gdm_wait_on_pid (worker->priv->child_pid);
|
||||
}
|
||||
|
||||
if (worker->priv->pam_handle != NULL) {
|
||||
gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
|
||||
}
|
||||
|
||||
+ jump_back_to_initial_vt (worker);
|
||||
+
|
||||
g_clear_object (&worker->priv->user_settings);
|
||||
g_free (worker->priv->service);
|
||||
g_free (worker->priv->x11_display_name);
|
||||
g_free (worker->priv->x11_authority_file);
|
||||
g_free (worker->priv->display_device);
|
||||
g_free (worker->priv->display_seat_id);
|
||||
g_free (worker->priv->hostname);
|
||||
g_free (worker->priv->username);
|
||||
g_free (worker->priv->server_address);
|
||||
g_strfreev (worker->priv->arguments);
|
||||
g_strfreev (worker->priv->extensions);
|
||||
|
||||
g_hash_table_unref (worker->priv->reauthentication_requests);
|
||||
|
||||
G_OBJECT_CLASS (gdm_session_worker_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GdmSessionWorker *
|
||||
gdm_session_worker_new (const char *address,
|
||||
gboolean is_reauth_session)
|
||||
{
|
||||
GObject *object;
|
||||
|
||||
object = g_object_new (GDM_TYPE_SESSION_WORKER,
|
||||
"server-address", address,
|
||||
"is-reauth-session", is_reauth_session,
|
||||
NULL);
|
||||
|
||||
return GDM_SESSION_WORKER (object);
|
||||
}
|
||||
diff --git a/daemon/org.freedesktop.DBus.xml b/daemon/org.freedesktop.DBus.xml
|
||||
new file mode 100644
|
||||
index 000000000..5e0814bde
|
||||
--- /dev/null
|
||||
+++ b/daemon/org.freedesktop.DBus.xml
|
||||
@@ -0,0 +1,12 @@
|
||||
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
||||
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
+<node>
|
||||
+ <interface name="org.freedesktop.DBus.Peer">
|
||||
+ <method name="GetMachineId">
|
||||
+ <arg direction="out" type="s"/>
|
||||
+ </method>
|
||||
+ <method name="Ping">
|
||||
+ </method>
|
||||
+ </interface>
|
||||
+</node>
|
||||
+
|
||||
--
|
||||
2.28.0
|
||||
|
@ -0,0 +1,164 @@
|
||||
From 417f0aed42959719c40f0f8ec65050dcf2510bd1 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Wed, 16 May 2018 14:10:34 +0100
|
||||
Subject: [PATCH 02/51] local-display-factory: Add
|
||||
gdm_local_display_factory_use_wayland() helper
|
||||
|
||||
Factor out the code which decides if Xorg or Wayland should be used into
|
||||
a helper function.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 23 +++++++++++++++--------
|
||||
1 file changed, 15 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 1a9196ee1..b21e3aee0 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -158,60 +158,73 @@ take_next_display_number (GdmLocalDisplayFactory *factory)
|
||||
ret = num + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
out:
|
||||
|
||||
/* now reserve this number */
|
||||
g_debug ("GdmLocalDisplayFactory: Reserving X display: %u", ret);
|
||||
g_hash_table_insert (factory->priv->used_display_numbers, GUINT_TO_POINTER (ret), NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_disposed (GdmLocalDisplayFactory *factory,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
g_debug ("GdmLocalDisplayFactory: Display %p disposed", display);
|
||||
}
|
||||
|
||||
static void
|
||||
store_display (GdmLocalDisplayFactory *factory,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
gdm_display_store_add (store, display);
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+gdm_local_display_factory_use_wayland (void)
|
||||
+{
|
||||
+#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
+ gboolean wayland_enabled = FALSE;
|
||||
+ if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
|
||||
+ if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
|
||||
+ return TRUE;
|
||||
+ }
|
||||
+#endif
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
Example:
|
||||
dbus-send --system --dest=org.gnome.DisplayManager \
|
||||
--type=method_call --print-reply --reply-timeout=2000 \
|
||||
/org/gnome/DisplayManager/Manager \
|
||||
org.gnome.DisplayManager.Manager.GetDisplays
|
||||
*/
|
||||
gboolean
|
||||
gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
|
||||
char **id,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
GdmDisplay *display = NULL;
|
||||
|
||||
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Creating transient display");
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
display = gdm_local_display_new ();
|
||||
#else
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
@@ -422,68 +435,62 @@ gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
|
||||
GVariant *array;
|
||||
GVariantIter iter;
|
||||
const char *seat;
|
||||
|
||||
result = g_dbus_connection_call_sync (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"ListSeats",
|
||||
NULL,
|
||||
G_VARIANT_TYPE ("(a(so))"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, &error);
|
||||
|
||||
if (!result) {
|
||||
g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
array = g_variant_get_child_value (result, 0);
|
||||
g_variant_iter_init (&iter, array);
|
||||
|
||||
while (g_variant_iter_loop (&iter, "(&so)", &seat, NULL)) {
|
||||
gboolean is_initial;
|
||||
const char *session_type = NULL;
|
||||
|
||||
if (g_strcmp0 (seat, "seat0") == 0) {
|
||||
is_initial = TRUE;
|
||||
-#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
- gboolean wayland_enabled = FALSE;
|
||||
- if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
|
||||
- if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) ) {
|
||||
- session_type = "wayland";
|
||||
- }
|
||||
- }
|
||||
-#endif
|
||||
+ if (gdm_local_display_factory_use_wayland ())
|
||||
+ session_type = "wayland";
|
||||
} else {
|
||||
is_initial = FALSE;
|
||||
}
|
||||
|
||||
create_display (factory, seat, session_type, is_initial);
|
||||
}
|
||||
|
||||
g_variant_unref (result);
|
||||
g_variant_unref (array);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_seat_new (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *seat;
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
create_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat, NULL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_seat_removed (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,87 @@
|
||||
From aeb88313c2110389ec530c8c7d5d816bac24d254 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 15 Sep 2020 00:41:00 -0400
|
||||
Subject: [PATCH 2/3] session: Don't leak remote greeter interface
|
||||
|
||||
XDMCP login screens get a "Remote Geeter Interface" exported over
|
||||
the bus connection (so the login window can provide a Disconnect
|
||||
button).
|
||||
|
||||
This interface is getting leaked when the session object is disposed,
|
||||
leaving the bus connection itself undisposed, which causes an fd
|
||||
leak.
|
||||
|
||||
This commit plugs the interface leak, and thus the fd leak.
|
||||
---
|
||||
daemon/gdm-session.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
|
||||
index 540a2534d..d6d8f128a 100644
|
||||
--- a/daemon/gdm-session.c
|
||||
+++ b/daemon/gdm-session.c
|
||||
@@ -3602,60 +3602,61 @@ gdm_session_get_property (GObject *object,
|
||||
break;
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
case PROP_IGNORE_WAYLAND:
|
||||
g_value_set_boolean (value, self->priv->ignore_wayland);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_dispose (GObject *object)
|
||||
{
|
||||
GdmSession *self;
|
||||
|
||||
self = GDM_SESSION (object);
|
||||
|
||||
g_debug ("GdmSession: Disposing session");
|
||||
|
||||
gdm_session_close (self);
|
||||
|
||||
g_clear_pointer (&self->priv->conversations,
|
||||
g_hash_table_unref);
|
||||
|
||||
g_clear_object (&self->priv->user_verifier_interface);
|
||||
g_clear_pointer (&self->priv->user_verifier_extensions,
|
||||
g_hash_table_unref);
|
||||
g_clear_object (&self->priv->greeter_interface);
|
||||
+ g_clear_object (&self->priv->remote_greeter_interface);
|
||||
g_clear_object (&self->priv->chooser_interface);
|
||||
|
||||
g_free (self->priv->display_name);
|
||||
self->priv->display_name = NULL;
|
||||
|
||||
g_free (self->priv->display_hostname);
|
||||
self->priv->display_hostname = NULL;
|
||||
|
||||
g_free (self->priv->display_device);
|
||||
self->priv->display_device = NULL;
|
||||
|
||||
g_free (self->priv->display_seat_id);
|
||||
self->priv->display_seat_id = NULL;
|
||||
|
||||
g_free (self->priv->display_x11_authority_file);
|
||||
self->priv->display_x11_authority_file = NULL;
|
||||
|
||||
g_strfreev (self->priv->conversation_environment);
|
||||
self->priv->conversation_environment = NULL;
|
||||
|
||||
if (self->priv->worker_server != NULL) {
|
||||
g_dbus_server_stop (self->priv->worker_server);
|
||||
g_clear_object (&self->priv->worker_server);
|
||||
}
|
||||
|
||||
if (self->priv->outside_server != NULL) {
|
||||
g_dbus_server_stop (self->priv->outside_server);
|
||||
g_clear_object (&self->priv->outside_server);
|
||||
}
|
||||
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,83 @@
|
||||
From db47f4de3aab9f4cd6b381ecd9341c94add59bf9 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Wed, 16 May 2018 18:36:50 +0100
|
||||
Subject: [PATCH 03/51] local-display-factory: Use correct session-type for new
|
||||
transient displays
|
||||
|
||||
Use the new gdm_local_display_factory_use_wayland() helper to correctly
|
||||
set the session-type properties for displays created through
|
||||
gdm_local_display_factory_create_transient_display().
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index b21e3aee0..e52360a56 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -194,60 +194,62 @@ gdm_local_display_factory_use_wayland (void)
|
||||
if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
Example:
|
||||
dbus-send --system --dest=org.gnome.DisplayManager \
|
||||
--type=method_call --print-reply --reply-timeout=2000 \
|
||||
/org/gnome/DisplayManager/Manager \
|
||||
org.gnome.DisplayManager.Manager.GetDisplays
|
||||
*/
|
||||
gboolean
|
||||
gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
|
||||
char **id,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
GdmDisplay *display = NULL;
|
||||
|
||||
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Creating transient display");
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
display = gdm_local_display_new ();
|
||||
+ if (gdm_local_display_factory_use_wayland ())
|
||||
+ g_object_set (G_OBJECT (display), "session-type", "wayland", NULL);
|
||||
#else
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_object_set (display,
|
||||
"seat-id", "seat0",
|
||||
"allow-timed-login", FALSE,
|
||||
NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (! gdm_display_get_id (display, id, NULL)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
/* ref either held by store or not at all */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,87 @@
|
||||
From 7c9e236f9015aae2ea5868b67ff8036766cb7099 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 15 Sep 2020 11:28:48 -0400
|
||||
Subject: [PATCH 3/3] xdmcp-display-factory: Clear launch environment when done
|
||||
with it
|
||||
|
||||
The XDMCP disply factory examines the sessions of its displays'
|
||||
launch environments when the displays change status.
|
||||
|
||||
Unfortunately it leaks a reference to the launch environment when
|
||||
doing that.
|
||||
|
||||
This commit fixes the reference leak which leads to an fd leak.
|
||||
---
|
||||
daemon/gdm-xdmcp-display-factory.c | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
|
||||
index 2e14beab4..98232113f 100644
|
||||
--- a/daemon/gdm-xdmcp-display-factory.c
|
||||
+++ b/daemon/gdm-xdmcp-display-factory.c
|
||||
@@ -2091,60 +2091,62 @@ on_display_status_changed (GdmDisplay *display,
|
||||
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
break;
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
if (session != NULL) {
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (session),
|
||||
G_CALLBACK (on_client_disconnected),
|
||||
display);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
break;
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
if (session != NULL) {
|
||||
g_signal_connect_object (G_OBJECT (session),
|
||||
"client-disconnected",
|
||||
G_CALLBACK (on_client_disconnected),
|
||||
display, G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (G_OBJECT (session),
|
||||
"disconnected",
|
||||
G_CALLBACK (on_client_disconnected),
|
||||
display, G_CONNECT_SWAPPED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
+
|
||||
+ g_clear_object (&launch_environment);
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
|
||||
const char *hostname,
|
||||
GdmAddress *address,
|
||||
int displaynum)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
GdmDisplayStore *store;
|
||||
gboolean use_chooser;
|
||||
|
||||
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
|
||||
hostname ? hostname : "(null)", displaynum);
|
||||
|
||||
use_chooser = FALSE;
|
||||
if (factory->priv->honor_indirect) {
|
||||
IndirectClient *ic;
|
||||
|
||||
ic = indirect_client_lookup (factory, address);
|
||||
|
||||
/* This was an indirect thingie and nothing was yet chosen,
|
||||
* use a chooser */
|
||||
if (ic != NULL && ic->chosen_address == NULL) {
|
||||
use_chooser = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_chooser) {
|
||||
display = gdm_xdmcp_chooser_display_new (hostname,
|
||||
--
|
||||
2.26.2
|
||||
|
@ -0,0 +1,137 @@
|
||||
From e2e5d2a7d73baa7c24d1f14b276cb653c06dd82f Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Wed, 1 Aug 2018 15:46:11 -0400
|
||||
Subject: [PATCH 04/51] manager: make get_login_window_session_id fail if no
|
||||
login screen
|
||||
|
||||
Right now we oddly succeed from get_login_window_session_id
|
||||
if we can't find a login window.
|
||||
|
||||
None of the caller expect that, so fail instead.
|
||||
---
|
||||
daemon/gdm-manager.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index e44b94373..a9d5628ea 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1372,113 +1372,113 @@ maybe_start_pending_initial_login (GdmManager *manager,
|
||||
NULL);
|
||||
|
||||
if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) {
|
||||
start_user_session (manager, operation);
|
||||
manager->priv->initial_login_operation = NULL;
|
||||
}
|
||||
|
||||
g_free (greeter_seat_id);
|
||||
g_free (user_session_seat_id);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_login_window_session_id (const char *seat_id,
|
||||
char **session_id)
|
||||
{
|
||||
gboolean ret;
|
||||
int res, i;
|
||||
char **sessions;
|
||||
char *service_id;
|
||||
char *service_class;
|
||||
char *state;
|
||||
|
||||
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
||||
if (res < 0) {
|
||||
g_debug ("Failed to determine sessions: %s", strerror (-res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sessions == NULL || sessions[0] == NULL) {
|
||||
*session_id = NULL;
|
||||
- ret = TRUE;
|
||||
+ ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
|
||||
res = sd_session_get_class (sessions[i], &service_class);
|
||||
if (res < 0) {
|
||||
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_class, "greeter") != 0) {
|
||||
free (service_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
free (service_class);
|
||||
|
||||
ret = sd_session_get_state (sessions[i], &state);
|
||||
if (ret < 0) {
|
||||
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (state, "closing") == 0) {
|
||||
free (state);
|
||||
continue;
|
||||
}
|
||||
free (state);
|
||||
|
||||
res = sd_session_get_service (sessions[i], &service_id);
|
||||
if (res < 0) {
|
||||
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
||||
*session_id = g_strdup (sessions[i]);
|
||||
ret = TRUE;
|
||||
|
||||
free (service_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
- ret = TRUE;
|
||||
+ ret = FALSE;
|
||||
|
||||
out:
|
||||
if (sessions) {
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_login_window_session_on_seat (GdmManager *self,
|
||||
const char *seat_id)
|
||||
{
|
||||
char *session_id;
|
||||
|
||||
if (!get_login_window_session_id (seat_id, &session_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
activate_session_id (self, seat_id, session_id);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_activate_other_session (GdmManager *self,
|
||||
GdmDisplay *old_display)
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
|
79
SOURCES/0005-manager-avoid-leaking-session_id.patch
Normal file
79
SOURCES/0005-manager-avoid-leaking-session_id.patch
Normal file
@ -0,0 +1,79 @@
|
||||
From 34238a9e845455ae2b92159c71b75b7abedc2eb9 Mon Sep 17 00:00:00 2001
|
||||
From: Lubomir Rintel <lkundrak@v3.sk>
|
||||
Date: Mon, 18 Jun 2018 12:33:42 +0200
|
||||
Subject: [PATCH 05/51] manager: avoid leaking session_id
|
||||
|
||||
get_login_window_session_id() duplicates the session id.
|
||||
---
|
||||
daemon/gdm-manager.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index a9d5628ea..71f55ec65 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1449,60 +1449,61 @@ get_login_window_session_id (const char *seat_id,
|
||||
|
||||
free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
|
||||
out:
|
||||
if (sessions) {
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_login_window_session_on_seat (GdmManager *self,
|
||||
const char *seat_id)
|
||||
{
|
||||
char *session_id;
|
||||
|
||||
if (!get_login_window_session_id (seat_id, &session_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
activate_session_id (self, seat_id, session_id);
|
||||
+ g_free (session_id);
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_activate_other_session (GdmManager *self,
|
||||
GdmDisplay *old_display)
|
||||
{
|
||||
char *seat_id = NULL;
|
||||
char *session_id;
|
||||
int ret;
|
||||
|
||||
g_object_get (G_OBJECT (old_display),
|
||||
"seat-id", &seat_id,
|
||||
NULL);
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (self->priv->display_store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) session_id);
|
||||
|
||||
if (display == NULL) {
|
||||
activate_login_window_session_on_seat (self, seat_id);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,89 @@
|
||||
From 454a3daad5148a8ef30cb298af82aa0713e73af7 Mon Sep 17 00:00:00 2001
|
||||
From: Lubomir Rintel <lkundrak@v3.sk>
|
||||
Date: Mon, 18 Jun 2018 12:33:51 +0200
|
||||
Subject: [PATCH 06/51] manager: gracefully handle the case of no session for
|
||||
login window
|
||||
|
||||
get_login_window_session_id() will return TRUE with session_id=NULL when
|
||||
there's no session. This restults in an assertion failure on
|
||||
constructing the o.fd.login1.Manager.ActivateSessionOnSeat() arguments:
|
||||
|
||||
GLib: g_variant_new_string: assertion 'string != NULL' failed
|
||||
---
|
||||
daemon/gdm-manager.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 71f55ec65..7a5554e9d 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1448,62 +1448,64 @@ get_login_window_session_id (const char *seat_id,
|
||||
}
|
||||
|
||||
free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
|
||||
out:
|
||||
if (sessions) {
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_login_window_session_on_seat (GdmManager *self,
|
||||
const char *seat_id)
|
||||
{
|
||||
char *session_id;
|
||||
|
||||
if (!get_login_window_session_id (seat_id, &session_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
- activate_session_id (self, seat_id, session_id);
|
||||
- g_free (session_id);
|
||||
+ if (session_id) {
|
||||
+ activate_session_id (self, seat_id, session_id);
|
||||
+ g_free (session_id);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_activate_other_session (GdmManager *self,
|
||||
GdmDisplay *old_display)
|
||||
{
|
||||
char *seat_id = NULL;
|
||||
char *session_id;
|
||||
int ret;
|
||||
|
||||
g_object_get (G_OBJECT (old_display),
|
||||
"seat-id", &seat_id,
|
||||
NULL);
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (self->priv->display_store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) session_id);
|
||||
|
||||
if (display == NULL) {
|
||||
activate_login_window_session_on_seat (self, seat_id);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
432
SOURCES/0007-common-dedupe-gdm_get_login_window_session_id.patch
Normal file
432
SOURCES/0007-common-dedupe-gdm_get_login_window_session_id.patch
Normal file
@ -0,0 +1,432 @@
|
||||
From 2fc9a5f9db7c9d2ab828bcff4ee5dec9c3cf3d3c Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Wed, 1 Aug 2018 16:34:30 -0400
|
||||
Subject: [PATCH 07/51] common: dedupe gdm_get_login_window_session_id
|
||||
|
||||
Right now there are two slightly different cut-and-pastes of
|
||||
the function to get the session id of the login session in
|
||||
the code.
|
||||
|
||||
This commit deduplicates them.
|
||||
---
|
||||
common/gdm-common.c | 47 ++++++++++++++++++++++++++++++++------------
|
||||
common/gdm-common.h | 2 ++
|
||||
daemon/gdm-manager.c | 4 ++--
|
||||
3 files changed, 38 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/common/gdm-common.c b/common/gdm-common.c
|
||||
index c44fa998d..00daf0df8 100644
|
||||
--- a/common/gdm-common.c
|
||||
+++ b/common/gdm-common.c
|
||||
@@ -364,186 +364,207 @@ create_transient_display (GDBusConnection *connection,
|
||||
|
||||
static gboolean
|
||||
activate_session_id (GDBusConnection *connection,
|
||||
const char *seat_id,
|
||||
const char *session_id)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
GVariant *reply;
|
||||
|
||||
reply = g_dbus_connection_call_sync (connection,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"ActivateSessionOnSeat",
|
||||
g_variant_new ("(ss)", session_id, seat_id),
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, &local_error);
|
||||
if (reply == NULL) {
|
||||
g_warning ("Unable to activate session: %s", local_error->message);
|
||||
g_error_free (local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_variant_unref (reply);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
-get_login_window_session_id (const char *seat_id,
|
||||
- char **session_id)
|
||||
+gboolean
|
||||
+gdm_get_login_window_session_id (const char *seat_id,
|
||||
+ char **session_id)
|
||||
{
|
||||
gboolean ret;
|
||||
int res, i;
|
||||
char **sessions;
|
||||
+ char *service_id;
|
||||
char *service_class;
|
||||
char *state;
|
||||
|
||||
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
||||
if (res < 0) {
|
||||
g_debug ("Failed to determine sessions: %s", strerror (-res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sessions == NULL || sessions[0] == NULL) {
|
||||
*session_id = NULL;
|
||||
- ret = TRUE;
|
||||
+ ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
+
|
||||
res = sd_session_get_class (sessions[i], &service_class);
|
||||
if (res < 0) {
|
||||
+ if (res == -ENOENT) {
|
||||
+ free (service_class);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_class, "greeter") != 0) {
|
||||
free (service_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
free (service_class);
|
||||
|
||||
ret = sd_session_get_state (sessions[i], &state);
|
||||
if (ret < 0) {
|
||||
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (state, "closing") == 0) {
|
||||
free (state);
|
||||
continue;
|
||||
}
|
||||
free (state);
|
||||
|
||||
- *session_id = g_strdup (sessions[i]);
|
||||
- ret = TRUE;
|
||||
- break;
|
||||
+ res = sd_session_get_service (sessions[i], &service_id);
|
||||
+ if (res < 0) {
|
||||
+ g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
||||
+ ret = FALSE;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
+ if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
||||
+ *session_id = g_strdup (sessions[i]);
|
||||
+ ret = TRUE;
|
||||
+
|
||||
+ free (service_id);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
- ret = TRUE;
|
||||
+ ret = FALSE;
|
||||
|
||||
out:
|
||||
- for (i = 0; sessions[i]; i ++) {
|
||||
- free (sessions[i]);
|
||||
- }
|
||||
+ if (sessions) {
|
||||
+ for (i = 0; sessions[i]; i ++) {
|
||||
+ free (sessions[i]);
|
||||
+ }
|
||||
|
||||
- free (sessions);
|
||||
+ free (sessions);
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
goto_login_session (GDBusConnection *connection,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
int res;
|
||||
char *our_session;
|
||||
char *session_id;
|
||||
char *seat_id;
|
||||
|
||||
ret = FALSE;
|
||||
session_id = NULL;
|
||||
seat_id = NULL;
|
||||
|
||||
/* First look for any existing LoginWindow sessions on the seat.
|
||||
If none are found, create a new one. */
|
||||
|
||||
/* Note that we mostly use free () here, instead of g_free ()
|
||||
* since the data allocated is from libsystemd-logind, which
|
||||
* does not use GLib's g_malloc (). */
|
||||
|
||||
res = sd_pid_get_session (0, &our_session);
|
||||
if (res < 0) {
|
||||
g_debug ("failed to determine own session: %s", strerror (-res));
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current session."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = sd_session_get_seat (our_session, &seat_id);
|
||||
free (our_session);
|
||||
if (res < 0) {
|
||||
g_debug ("failed to determine own seat: %s", strerror (-res));
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current seat."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = sd_seat_can_multi_session (seat_id);
|
||||
if (res < 0) {
|
||||
free (seat_id);
|
||||
|
||||
g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to determine whether to switch to an existing login screen or start up a new login screen."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
free (seat_id);
|
||||
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to start up a new login screen."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
- res = get_login_window_session_id (seat_id, &session_id);
|
||||
+ res = gdm_get_login_window_session_id (seat_id, &session_id);
|
||||
if (res && session_id != NULL) {
|
||||
res = activate_session_id (connection, seat_id, session_id);
|
||||
|
||||
if (res) {
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (! ret && g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
res = create_transient_display (connection, error);
|
||||
if (res) {
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
free (seat_id);
|
||||
g_free (session_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_goto_login_session (GError **error)
|
||||
{
|
||||
GError *local_error;
|
||||
GDBusConnection *connection;
|
||||
|
||||
local_error = NULL;
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local_error);
|
||||
if (connection == NULL) {
|
||||
diff --git a/common/gdm-common.h b/common/gdm-common.h
|
||||
index 8d83a1246..c9cbd9c48 100644
|
||||
--- a/common/gdm-common.h
|
||||
+++ b/common/gdm-common.h
|
||||
@@ -26,51 +26,53 @@
|
||||
#include <errno.h>
|
||||
|
||||
#define VE_IGNORE_EINTR(expr) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
expr; \
|
||||
} while G_UNLIKELY (errno == EINTR);
|
||||
|
||||
GQuark gdm_common_error_quark (void);
|
||||
#define GDM_COMMON_ERROR gdm_common_error_quark()
|
||||
|
||||
typedef char * (*GdmExpandVarFunc) (const char *var,
|
||||
gpointer user_data);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
int gdm_wait_on_pid (int pid);
|
||||
int gdm_wait_on_and_disown_pid (int pid,
|
||||
int timeout);
|
||||
int gdm_signal_pid (int pid,
|
||||
int signal);
|
||||
gboolean gdm_get_pwent_for_name (const char *name,
|
||||
struct passwd **pwentp);
|
||||
|
||||
gboolean gdm_clear_close_on_exec_flag (int fd);
|
||||
|
||||
const char * gdm_make_temp_dir (char *template);
|
||||
|
||||
char *gdm_generate_random_bytes (gsize size,
|
||||
GError **error);
|
||||
+gboolean gdm_get_login_window_session_id (const char *seat_id,
|
||||
+ char **session_id);
|
||||
gboolean gdm_goto_login_session (GError **error);
|
||||
|
||||
GPtrArray *gdm_get_script_environment (const char *username,
|
||||
const char *display_name,
|
||||
const char *display_hostname,
|
||||
const char *display_x11_authority_file);
|
||||
gboolean gdm_run_script (const char *dir,
|
||||
const char *username,
|
||||
const char *display_name,
|
||||
const char *display_hostname,
|
||||
const char *display_x11_authority_file);
|
||||
|
||||
gboolean gdm_shell_var_is_valid_char (char c,
|
||||
gboolean first);
|
||||
char * gdm_shell_expand (const char *str,
|
||||
GdmExpandVarFunc expand_func,
|
||||
gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GDM_COMMON_H */
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 7a5554e9d..375ef6f80 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1444,61 +1444,61 @@ get_login_window_session_id (const char *seat_id,
|
||||
ret = TRUE;
|
||||
|
||||
free (service_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
|
||||
out:
|
||||
if (sessions) {
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_login_window_session_on_seat (GdmManager *self,
|
||||
const char *seat_id)
|
||||
{
|
||||
char *session_id;
|
||||
|
||||
- if (!get_login_window_session_id (seat_id, &session_id)) {
|
||||
+ if (!gdm_get_login_window_session_id (seat_id, &session_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_id) {
|
||||
activate_session_id (self, seat_id, session_id);
|
||||
g_free (session_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_activate_other_session (GdmManager *self,
|
||||
GdmDisplay *old_display)
|
||||
{
|
||||
char *seat_id = NULL;
|
||||
char *session_id;
|
||||
int ret;
|
||||
|
||||
g_object_get (G_OBJECT (old_display),
|
||||
"seat-id", &seat_id,
|
||||
NULL);
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (self->priv->display_store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) session_id);
|
||||
|
||||
@@ -2082,61 +2082,61 @@ on_user_session_exited (GdmSession *session,
|
||||
|
||||
static void
|
||||
on_user_session_died (GdmSession *session,
|
||||
int signal_number,
|
||||
GdmManager *manager)
|
||||
{
|
||||
g_debug ("GdmManager: session died with signal %s", strsignal (signal_number));
|
||||
remove_user_session (manager, session);
|
||||
}
|
||||
|
||||
static char *
|
||||
get_display_device (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
/* systemd finds the display device out on its own based on the display */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
on_session_reauthenticated (GdmSession *session,
|
||||
const char *service_name,
|
||||
GdmManager *manager)
|
||||
{
|
||||
gboolean fail_if_already_switched = FALSE;
|
||||
|
||||
if (gdm_session_get_display_mode (session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
|
||||
const char *seat_id;
|
||||
char *session_id;
|
||||
|
||||
seat_id = gdm_session_get_display_seat_id (session);
|
||||
- if (get_login_window_session_id (seat_id, &session_id)) {
|
||||
+ if (gdm_get_login_window_session_id (seat_id, &session_id)) {
|
||||
GdmDisplay *display = gdm_display_store_find (manager->priv->display_store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) session_id);
|
||||
|
||||
if (display != NULL) {
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
}
|
||||
g_free (session_id);
|
||||
}
|
||||
}
|
||||
|
||||
/* There should already be a session running, so jump to its
|
||||
* VT. In the event we're already on the right VT, (i.e. user
|
||||
* used an unlock screen instead of a user switched login screen),
|
||||
* then silently succeed and unlock the session.
|
||||
*/
|
||||
switch_to_compatible_user_session (manager, session, fail_if_already_switched);
|
||||
}
|
||||
|
||||
static void
|
||||
on_session_client_ready_for_session_to_start (GdmSession *session,
|
||||
const char *service_name,
|
||||
gboolean client_is_ready,
|
||||
GdmManager *manager)
|
||||
{
|
||||
gboolean waiting_to_start_user_session;
|
||||
|
||||
if (client_is_ready) {
|
||||
--
|
||||
2.27.0
|
||||
|
401
SOURCES/0008-common-dedupe-activate_session_id.patch
Normal file
401
SOURCES/0008-common-dedupe-activate_session_id.patch
Normal file
@ -0,0 +1,401 @@
|
||||
From 9d8e72ea9171566e9d74caaf28c8b5933ef34874 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 2 Aug 2018 14:00:46 -0400
|
||||
Subject: [PATCH 08/51] common: dedupe activate_session_id
|
||||
|
||||
Right now there are three copies of activate_session_id.
|
||||
|
||||
This commit consolidates the code to gdm-common.c
|
||||
---
|
||||
common/gdm-common.c | 10 +++++-----
|
||||
common/gdm-common.h | 6 ++++++
|
||||
daemon/gdm-manager.c | 33 +--------------------------------
|
||||
3 files changed, 12 insertions(+), 37 deletions(-)
|
||||
|
||||
diff --git a/common/gdm-common.c b/common/gdm-common.c
|
||||
index 00daf0df8..59317a889 100644
|
||||
--- a/common/gdm-common.c
|
||||
+++ b/common/gdm-common.c
|
||||
@@ -335,64 +335,64 @@ static gboolean
|
||||
create_transient_display (GDBusConnection *connection,
|
||||
GError **error)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
GVariant *reply;
|
||||
const char *value;
|
||||
|
||||
reply = g_dbus_connection_call_sync (connection,
|
||||
GDM_DBUS_NAME,
|
||||
GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
|
||||
GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
|
||||
"CreateTransientDisplay",
|
||||
NULL, /* parameters */
|
||||
G_VARIANT_TYPE ("(o)"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, &local_error);
|
||||
if (reply == NULL) {
|
||||
g_warning ("Unable to create transient display: %s", local_error->message);
|
||||
g_propagate_error (error, local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_variant_get (reply, "(&o)", &value);
|
||||
g_debug ("Started %s", value);
|
||||
|
||||
g_variant_unref (reply);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
-activate_session_id (GDBusConnection *connection,
|
||||
- const char *seat_id,
|
||||
- const char *session_id)
|
||||
+gboolean
|
||||
+gdm_activate_session_by_id (GDBusConnection *connection,
|
||||
+ const char *seat_id,
|
||||
+ const char *session_id)
|
||||
{
|
||||
GError *local_error = NULL;
|
||||
GVariant *reply;
|
||||
|
||||
reply = g_dbus_connection_call_sync (connection,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"ActivateSessionOnSeat",
|
||||
g_variant_new ("(ss)", session_id, seat_id),
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, &local_error);
|
||||
if (reply == NULL) {
|
||||
g_warning ("Unable to activate session: %s", local_error->message);
|
||||
g_error_free (local_error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_variant_unref (reply);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_get_login_window_session_id (const char *seat_id,
|
||||
char **session_id)
|
||||
{
|
||||
gboolean ret;
|
||||
@@ -512,61 +512,61 @@ goto_login_session (GDBusConnection *connection,
|
||||
|
||||
res = sd_session_get_seat (our_session, &seat_id);
|
||||
free (our_session);
|
||||
if (res < 0) {
|
||||
g_debug ("failed to determine own seat: %s", strerror (-res));
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current seat."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = sd_seat_can_multi_session (seat_id);
|
||||
if (res < 0) {
|
||||
free (seat_id);
|
||||
|
||||
g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to determine whether to switch to an existing login screen or start up a new login screen."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (res == 0) {
|
||||
free (seat_id);
|
||||
|
||||
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to start up a new login screen."));
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
res = gdm_get_login_window_session_id (seat_id, &session_id);
|
||||
if (res && session_id != NULL) {
|
||||
- res = activate_session_id (connection, seat_id, session_id);
|
||||
+ res = gdm_activate_session_by_id (connection, seat_id, session_id);
|
||||
|
||||
if (res) {
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (! ret && g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
res = create_transient_display (connection, error);
|
||||
if (res) {
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
free (seat_id);
|
||||
g_free (session_id);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_goto_login_session (GError **error)
|
||||
{
|
||||
GError *local_error;
|
||||
GDBusConnection *connection;
|
||||
|
||||
local_error = NULL;
|
||||
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local_error);
|
||||
if (connection == NULL) {
|
||||
g_debug ("Failed to connect to the D-Bus daemon: %s", local_error->message);
|
||||
g_propagate_error (error, local_error);
|
||||
diff --git a/common/gdm-common.h b/common/gdm-common.h
|
||||
index c9cbd9c48..3fbf07653 100644
|
||||
--- a/common/gdm-common.h
|
||||
+++ b/common/gdm-common.h
|
||||
@@ -1,78 +1,84 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef _GDM_COMMON_H
|
||||
#define _GDM_COMMON_H
|
||||
|
||||
#include <glib-unix.h>
|
||||
+#include <gio/gio.h>
|
||||
+
|
||||
#include <pwd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define VE_IGNORE_EINTR(expr) \
|
||||
do { \
|
||||
errno = 0; \
|
||||
expr; \
|
||||
} while G_UNLIKELY (errno == EINTR);
|
||||
|
||||
GQuark gdm_common_error_quark (void);
|
||||
#define GDM_COMMON_ERROR gdm_common_error_quark()
|
||||
|
||||
typedef char * (*GdmExpandVarFunc) (const char *var,
|
||||
gpointer user_data);
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
int gdm_wait_on_pid (int pid);
|
||||
int gdm_wait_on_and_disown_pid (int pid,
|
||||
int timeout);
|
||||
int gdm_signal_pid (int pid,
|
||||
int signal);
|
||||
gboolean gdm_get_pwent_for_name (const char *name,
|
||||
struct passwd **pwentp);
|
||||
|
||||
gboolean gdm_clear_close_on_exec_flag (int fd);
|
||||
|
||||
const char * gdm_make_temp_dir (char *template);
|
||||
|
||||
char *gdm_generate_random_bytes (gsize size,
|
||||
GError **error);
|
||||
gboolean gdm_get_login_window_session_id (const char *seat_id,
|
||||
char **session_id);
|
||||
gboolean gdm_goto_login_session (GError **error);
|
||||
|
||||
GPtrArray *gdm_get_script_environment (const char *username,
|
||||
const char *display_name,
|
||||
const char *display_hostname,
|
||||
const char *display_x11_authority_file);
|
||||
gboolean gdm_run_script (const char *dir,
|
||||
const char *username,
|
||||
const char *display_name,
|
||||
const char *display_hostname,
|
||||
const char *display_x11_authority_file);
|
||||
|
||||
gboolean gdm_shell_var_is_valid_char (char c,
|
||||
gboolean first);
|
||||
char * gdm_shell_expand (const char *str,
|
||||
GdmExpandVarFunc expand_func,
|
||||
gpointer user_data);
|
||||
|
||||
+gboolean gdm_activate_session_by_id (GDBusConnection *connection,
|
||||
+ const char *seat_id,
|
||||
+ const char *session_id);
|
||||
+
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _GDM_COMMON_H */
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 375ef6f80..617ee36f0 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -267,91 +267,60 @@ lookup_by_session_id (const char *id,
|
||||
|
||||
static gboolean
|
||||
is_login_session (GdmManager *self,
|
||||
const char *session_id,
|
||||
GError **error)
|
||||
{
|
||||
char *session_class = NULL;
|
||||
int ret;
|
||||
|
||||
ret = sd_session_get_class (session_id, &session_class);
|
||||
|
||||
if (ret < 0) {
|
||||
g_set_error (error,
|
||||
GDM_DISPLAY_ERROR,
|
||||
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
|
||||
"Error getting class for session id %s from systemd: %s",
|
||||
session_id,
|
||||
g_strerror (-ret));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (session_class, "greeter") != 0) {
|
||||
g_free (session_class);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_free (session_class);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
-activate_session_id (GdmManager *manager,
|
||||
- const char *seat_id,
|
||||
- const char *session_id)
|
||||
-{
|
||||
- GError *error = NULL;
|
||||
- GVariant *reply;
|
||||
-
|
||||
- reply = g_dbus_connection_call_sync (manager->priv->connection,
|
||||
- "org.freedesktop.login1",
|
||||
- "/org/freedesktop/login1",
|
||||
- "org.freedesktop.login1.Manager",
|
||||
- "ActivateSessionOnSeat",
|
||||
- g_variant_new ("(ss)", session_id, seat_id),
|
||||
- NULL, /* expected reply */
|
||||
- G_DBUS_CALL_FLAGS_NONE,
|
||||
- -1,
|
||||
- NULL,
|
||||
- &error);
|
||||
- if (reply == NULL) {
|
||||
- g_debug ("GdmManager: logind 'ActivateSessionOnSeat' %s raised:\n %s\n\n",
|
||||
- g_dbus_error_get_remote_error (error), error->message);
|
||||
- g_error_free (error);
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- g_variant_unref (reply);
|
||||
-
|
||||
- return TRUE;
|
||||
-}
|
||||
-
|
||||
static gboolean
|
||||
session_unlock (GdmManager *manager,
|
||||
const char *ssid)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *reply;
|
||||
|
||||
g_debug ("Unlocking session %s", ssid);
|
||||
|
||||
reply = g_dbus_connection_call_sync (manager->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"UnlockSession",
|
||||
g_variant_new ("(s)", ssid),
|
||||
NULL, /* expected reply */
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
&error);
|
||||
if (reply == NULL) {
|
||||
g_debug ("GdmManager: logind 'UnlockSession' %s raised:\n %s\n\n",
|
||||
g_dbus_error_get_remote_error (error), error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_variant_unref (reply);
|
||||
|
||||
return TRUE;
|
||||
@@ -627,61 +596,61 @@ switch_to_compatible_user_session (GdmManager *manager,
|
||||
ret = FALSE;
|
||||
|
||||
username = gdm_session_get_username (session);
|
||||
seat_id = gdm_session_get_display_seat_id (session);
|
||||
|
||||
if (!fail_if_already_switched)
|
||||
ssid_to_activate = gdm_session_get_session_id (session);
|
||||
|
||||
if (ssid_to_activate == NULL) {
|
||||
if (!seat_id || !sd_seat_can_multi_session (seat_id)) {
|
||||
g_debug ("GdmManager: unable to activate existing sessions from login screen unless on seat0");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!fail_if_already_switched) {
|
||||
session = NULL;
|
||||
}
|
||||
|
||||
existing_session = find_session_for_user_on_seat (manager, username, seat_id, session);
|
||||
|
||||
if (existing_session != NULL) {
|
||||
ssid_to_activate = gdm_session_get_session_id (existing_session);
|
||||
}
|
||||
}
|
||||
|
||||
if (ssid_to_activate == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (seat_id != NULL) {
|
||||
- res = activate_session_id (manager, seat_id, ssid_to_activate);
|
||||
+ res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate);
|
||||
if (! res) {
|
||||
g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
res = session_unlock (manager, ssid_to_activate);
|
||||
if (!res) {
|
||||
/* this isn't fatal */
|
||||
g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
get_display_for_user_session (GdmSession *session)
|
||||
{
|
||||
return g_object_get_data (G_OBJECT (session), "gdm-display");
|
||||
}
|
||||
|
||||
static GdmSession *
|
||||
get_user_session_for_display (GdmDisplay *display)
|
||||
{
|
||||
if (display == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,103 @@
|
||||
From 5bc19a4eb6de02ba549252026911dcce86e0fc21 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 22 Jun 2018 14:44:11 -0400
|
||||
Subject: [PATCH 09/51] manager: plug leak in maybe_activate_other_session
|
||||
|
||||
The function asks logind what the currently active session is on the
|
||||
given seat. It then leaks the response.
|
||||
|
||||
This commit plugs the leak.
|
||||
---
|
||||
daemon/gdm-manager.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 617ee36f0..a4dad92ee 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1428,79 +1428,81 @@ out:
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
activate_login_window_session_on_seat (GdmManager *self,
|
||||
const char *seat_id)
|
||||
{
|
||||
char *session_id;
|
||||
|
||||
if (!gdm_get_login_window_session_id (seat_id, &session_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_id) {
|
||||
activate_session_id (self, seat_id, session_id);
|
||||
g_free (session_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_activate_other_session (GdmManager *self,
|
||||
GdmDisplay *old_display)
|
||||
{
|
||||
char *seat_id = NULL;
|
||||
- char *session_id;
|
||||
+ char *session_id = NULL;
|
||||
int ret;
|
||||
|
||||
g_object_get (G_OBJECT (old_display),
|
||||
"seat-id", &seat_id,
|
||||
NULL);
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (self->priv->display_store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) session_id);
|
||||
|
||||
if (display == NULL) {
|
||||
activate_login_window_session_on_seat (self, seat_id);
|
||||
}
|
||||
+
|
||||
+ g_free (session_id);
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_username_for_greeter_display (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
if (doing_initial_setup) {
|
||||
return INITIAL_SETUP_USERNAME;
|
||||
} else {
|
||||
return GDM_USERNAME;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_automatic_login_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
GdmSession *session;
|
||||
char *display_session_type = NULL;
|
||||
gboolean is_initial;
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,92 @@
|
||||
From 2ec1b65c7bc2cefeabbd9a7a3a50436e1233804c Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 22 Jun 2018 14:55:39 -0400
|
||||
Subject: [PATCH 10/51] manager: start login screen if old one is finished
|
||||
|
||||
Since commit 22c332ba we try to start a login screen if we end up
|
||||
on an empty VT and there isn't one running.
|
||||
|
||||
Unfortunately the check for "is on an empty VT" is a little busted.
|
||||
It counts the VT has non-empty if there's a display associated with
|
||||
it, even if that display is in the FINISHED state about to be
|
||||
reaped.
|
||||
|
||||
That means, in some cases, we'll still leave the user on an empty
|
||||
VT with no login screen.
|
||||
|
||||
This commit addresses the problem by explicitly checking for
|
||||
FINISHED displays, and proceeding even in their presense.
|
||||
---
|
||||
daemon/gdm-manager.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index a4dad92ee..a6f13dec7 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1444,61 +1444,61 @@ activate_login_window_session_on_seat (GdmManager *self,
|
||||
return;
|
||||
}
|
||||
|
||||
if (session_id) {
|
||||
activate_session_id (self, seat_id, session_id);
|
||||
g_free (session_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_activate_other_session (GdmManager *self,
|
||||
GdmDisplay *old_display)
|
||||
{
|
||||
char *seat_id = NULL;
|
||||
char *session_id = NULL;
|
||||
int ret;
|
||||
|
||||
g_object_get (G_OBJECT (old_display),
|
||||
"seat-id", &seat_id,
|
||||
NULL);
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (self->priv->display_store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) session_id);
|
||||
|
||||
- if (display == NULL) {
|
||||
+ if (display == NULL || gdm_display_get_status (display) == GDM_DISPLAY_FINISHED) {
|
||||
activate_login_window_session_on_seat (self, seat_id);
|
||||
}
|
||||
|
||||
g_free (session_id);
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_username_for_greeter_display (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
if (doing_initial_setup) {
|
||||
return INITIAL_SETUP_USERNAME;
|
||||
} else {
|
||||
return GDM_USERNAME;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_automatic_login_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,127 @@
|
||||
From 67d29b19ff4e53d58879b14c2e79a3bda419576f Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 22 Jun 2018 15:26:03 -0400
|
||||
Subject: [PATCH 11/51] manager: don't bail if session disappears out from
|
||||
under us
|
||||
|
||||
It's entirely possible for a session returned by
|
||||
sd_seat_get_sessions to disappear immediately after the
|
||||
sd_seat_get_sessions call returns. This is especially
|
||||
likely at logout time where the session will briefly be
|
||||
in the "closing" state before getting reaped.
|
||||
|
||||
If that happens when we're looking for a greeter session, we
|
||||
stop looking for a greeter session and bail out all confused.
|
||||
|
||||
This commit fixes the confusion by gracefully handling the
|
||||
session disappearing by just proceeding to the next session
|
||||
in the list.
|
||||
---
|
||||
daemon/gdm-manager.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index a6f13dec7..ede22e771 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1349,87 +1349,97 @@ maybe_start_pending_initial_login (GdmManager *manager,
|
||||
g_free (user_session_seat_id);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_login_window_session_id (const char *seat_id,
|
||||
char **session_id)
|
||||
{
|
||||
gboolean ret;
|
||||
int res, i;
|
||||
char **sessions;
|
||||
char *service_id;
|
||||
char *service_class;
|
||||
char *state;
|
||||
|
||||
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
||||
if (res < 0) {
|
||||
g_debug ("Failed to determine sessions: %s", strerror (-res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sessions == NULL || sessions[0] == NULL) {
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
|
||||
res = sd_session_get_class (sessions[i], &service_class);
|
||||
if (res < 0) {
|
||||
+ if (res == -ENOENT) {
|
||||
+ free (service_class);
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_class, "greeter") != 0) {
|
||||
free (service_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
free (service_class);
|
||||
|
||||
ret = sd_session_get_state (sessions[i], &state);
|
||||
if (ret < 0) {
|
||||
+ if (res == -ENOENT)
|
||||
+ continue;
|
||||
+
|
||||
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (state, "closing") == 0) {
|
||||
free (state);
|
||||
continue;
|
||||
}
|
||||
free (state);
|
||||
|
||||
res = sd_session_get_service (sessions[i], &service_id);
|
||||
if (res < 0) {
|
||||
+ if (res == -ENOENT)
|
||||
+ continue;
|
||||
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
||||
*session_id = g_strdup (sessions[i]);
|
||||
ret = TRUE;
|
||||
|
||||
free (service_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
|
||||
out:
|
||||
if (sessions) {
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,563 @@
|
||||
From 9a3e9cb9a6bbf68ed6eb9f13d143a63af940f3ae Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Mon, 30 Jul 2018 16:21:29 -0400
|
||||
Subject: [PATCH 12/51] daemon: try harder to get to a login screen at logout
|
||||
|
||||
commit 22c332ba and some follow up commits try to ensure the
|
||||
user never stays on a blank VT by jumping to a login screen in
|
||||
the event they'd end up on one.
|
||||
|
||||
Unfortunately, that part of the code can't start a login screen
|
||||
if there's not one running at all.
|
||||
|
||||
This commit moves the code to GdmLocalDisplyFactory where the
|
||||
login screens are created, so users won't end up on a blank
|
||||
VT even if no login screen is yet running.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 36 +++++++-
|
||||
daemon/gdm-manager.c | 143 -----------------------------
|
||||
2 files changed, 31 insertions(+), 148 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index e52360a56..0e454c880 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -1,60 +1,62 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
|
||||
*
|
||||
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
+#include <systemd/sd-login.h>
|
||||
+
|
||||
#include "gdm-common.h"
|
||||
#include "gdm-manager.h"
|
||||
#include "gdm-display-factory.h"
|
||||
#include "gdm-local-display-factory.h"
|
||||
#include "gdm-local-display-factory-glue.h"
|
||||
|
||||
#include "gdm-settings-keys.h"
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-display-store.h"
|
||||
#include "gdm-local-display.h"
|
||||
#include "gdm-legacy-display.h"
|
||||
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
||||
|
||||
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
||||
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
||||
|
||||
#define MAX_DISPLAY_FAILURES 5
|
||||
|
||||
struct GdmLocalDisplayFactoryPrivate
|
||||
{
|
||||
GdmDBusLocalDisplayFactory *skeleton;
|
||||
GDBusConnection *connection;
|
||||
GHashTable *used_display_numbers;
|
||||
|
||||
/* FIXME: this needs to be per seat? */
|
||||
guint num_failures;
|
||||
|
||||
guint seat_new_id;
|
||||
@@ -240,174 +242,198 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (! gdm_display_get_id (display, id, NULL)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
/* ref either held by store or not at all */
|
||||
g_object_unref (display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
int status;
|
||||
int num;
|
||||
char *seat_id = NULL;
|
||||
char *session_type = NULL;
|
||||
+ char *session_class = NULL;
|
||||
gboolean is_initial = TRUE;
|
||||
gboolean is_local = TRUE;
|
||||
|
||||
num = -1;
|
||||
gdm_display_get_x11_display_number (display, &num, NULL);
|
||||
|
||||
g_object_get (display,
|
||||
"seat-id", &seat_id,
|
||||
"is-initial", &is_initial,
|
||||
"is-local", &is_local,
|
||||
"session-type", &session_type,
|
||||
+ "session-class", &session_class,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
/* remove the display number from factory->priv->used_display_numbers
|
||||
so that it may be reused */
|
||||
if (num != -1) {
|
||||
g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
|
||||
}
|
||||
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
/* if this is a local display, do a full resync. Only
|
||||
* seats without displays will get created anyway. This
|
||||
* ensures we get a new login screen when the user logs out,
|
||||
* if there isn't one.
|
||||
*/
|
||||
- if (is_local) {
|
||||
+ if (is_local && g_strcmp0 (session_class, "greeter") != 0) {
|
||||
/* reset num failures */
|
||||
factory->priv->num_failures = 0;
|
||||
|
||||
gdm_local_display_factory_sync_seats (factory);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
/* leave the display number in factory->priv->used_display_numbers
|
||||
so that it doesn't get reused */
|
||||
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
/* Create a new equivalent display if it was static */
|
||||
if (is_local) {
|
||||
|
||||
factory->priv->num_failures++;
|
||||
|
||||
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
||||
/* oh shit */
|
||||
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
||||
} else {
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
if (g_strcmp0 (session_type, "wayland") == 0) {
|
||||
g_free (session_type);
|
||||
session_type = NULL;
|
||||
|
||||
/* workaround logind race for now
|
||||
* bug 1643874
|
||||
*/
|
||||
g_usleep (2 * G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
#endif
|
||||
create_display (factory, seat_id, session_type, is_initial);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
break;
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
break;
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
g_free (session_type);
|
||||
+ g_free (session_class);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_by_seat_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
char *current;
|
||||
gboolean res;
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
||||
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
+ char *active_session_id = NULL;
|
||||
+ int ret;
|
||||
|
||||
- /* Ensure we don't create the same display more than once */
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
- if (display != NULL) {
|
||||
- return NULL;
|
||||
+
|
||||
+ ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
||||
+
|
||||
+ if (ret == 0) {
|
||||
+ char *login_session_id = NULL;
|
||||
+
|
||||
+ /* If we already have a login window, switch to it */
|
||||
+ if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
+ if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
+ gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
+ }
|
||||
+ g_clear_pointer (&login_session_id, g_free);
|
||||
+ g_clear_pointer (&active_session_id, g_free);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ g_clear_pointer (&active_session_id, g_free);
|
||||
+ } else {
|
||||
+ /* Ensure we don't create the same display more than once */
|
||||
+ display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
+
|
||||
+ if (display != NULL) {
|
||||
+ return NULL;
|
||||
+ }
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
|
||||
g_object_set (display, "seat-id", seat_id, NULL);
|
||||
g_object_set (display, "is-initial", initial, NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
/* let store own the ref */
|
||||
g_object_unref (display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index ede22e771..80f60d24c 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1322,202 +1322,60 @@ maybe_start_pending_initial_login (GdmManager *manager,
|
||||
char *user_session_seat_id = NULL;
|
||||
|
||||
/* There may be a user session waiting to be started.
|
||||
* This would happen if we couldn't start it earlier because
|
||||
* the login screen X server was coming up and two X servers
|
||||
* can't be started on the same seat at the same time.
|
||||
*/
|
||||
|
||||
if (manager->priv->initial_login_operation == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
operation = manager->priv->initial_login_operation;
|
||||
|
||||
g_object_get (G_OBJECT (greeter_display),
|
||||
"seat-id", &greeter_seat_id,
|
||||
NULL);
|
||||
g_object_get (G_OBJECT (operation->session),
|
||||
"display-seat-id", &user_session_seat_id,
|
||||
NULL);
|
||||
|
||||
if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) {
|
||||
start_user_session (manager, operation);
|
||||
manager->priv->initial_login_operation = NULL;
|
||||
}
|
||||
|
||||
g_free (greeter_seat_id);
|
||||
g_free (user_session_seat_id);
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
-get_login_window_session_id (const char *seat_id,
|
||||
- char **session_id)
|
||||
-{
|
||||
- gboolean ret;
|
||||
- int res, i;
|
||||
- char **sessions;
|
||||
- char *service_id;
|
||||
- char *service_class;
|
||||
- char *state;
|
||||
-
|
||||
- res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
||||
- if (res < 0) {
|
||||
- g_debug ("Failed to determine sessions: %s", strerror (-res));
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- if (sessions == NULL || sessions[0] == NULL) {
|
||||
- *session_id = NULL;
|
||||
- ret = FALSE;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- for (i = 0; sessions[i]; i ++) {
|
||||
-
|
||||
- res = sd_session_get_class (sessions[i], &service_class);
|
||||
- if (res < 0) {
|
||||
- if (res == -ENOENT) {
|
||||
- free (service_class);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
||||
- ret = FALSE;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (strcmp (service_class, "greeter") != 0) {
|
||||
- free (service_class);
|
||||
- continue;
|
||||
- }
|
||||
-
|
||||
- free (service_class);
|
||||
-
|
||||
- ret = sd_session_get_state (sessions[i], &state);
|
||||
- if (ret < 0) {
|
||||
- if (res == -ENOENT)
|
||||
- continue;
|
||||
-
|
||||
- g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
||||
- ret = FALSE;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (g_strcmp0 (state, "closing") == 0) {
|
||||
- free (state);
|
||||
- continue;
|
||||
- }
|
||||
- free (state);
|
||||
-
|
||||
- res = sd_session_get_service (sessions[i], &service_id);
|
||||
- if (res < 0) {
|
||||
- if (res == -ENOENT)
|
||||
- continue;
|
||||
- g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
||||
- ret = FALSE;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
||||
- *session_id = g_strdup (sessions[i]);
|
||||
- ret = TRUE;
|
||||
-
|
||||
- free (service_id);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- free (service_id);
|
||||
- }
|
||||
-
|
||||
- *session_id = NULL;
|
||||
- ret = FALSE;
|
||||
-
|
||||
-out:
|
||||
- if (sessions) {
|
||||
- for (i = 0; sessions[i]; i ++) {
|
||||
- free (sessions[i]);
|
||||
- }
|
||||
-
|
||||
- free (sessions);
|
||||
- }
|
||||
-
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-activate_login_window_session_on_seat (GdmManager *self,
|
||||
- const char *seat_id)
|
||||
-{
|
||||
- char *session_id;
|
||||
-
|
||||
- if (!gdm_get_login_window_session_id (seat_id, &session_id)) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- if (session_id) {
|
||||
- activate_session_id (self, seat_id, session_id);
|
||||
- g_free (session_id);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static void
|
||||
-maybe_activate_other_session (GdmManager *self,
|
||||
- GdmDisplay *old_display)
|
||||
-{
|
||||
- char *seat_id = NULL;
|
||||
- char *session_id = NULL;
|
||||
- int ret;
|
||||
-
|
||||
- g_object_get (G_OBJECT (old_display),
|
||||
- "seat-id", &seat_id,
|
||||
- NULL);
|
||||
-
|
||||
- ret = sd_seat_get_active (seat_id, &session_id, NULL);
|
||||
-
|
||||
- if (ret == 0) {
|
||||
- GdmDisplay *display;
|
||||
-
|
||||
- display = gdm_display_store_find (self->priv->display_store,
|
||||
- lookup_by_session_id,
|
||||
- (gpointer) session_id);
|
||||
-
|
||||
- if (display == NULL || gdm_display_get_status (display) == GDM_DISPLAY_FINISHED) {
|
||||
- activate_login_window_session_on_seat (self, seat_id);
|
||||
- }
|
||||
-
|
||||
- g_free (session_id);
|
||||
- }
|
||||
-
|
||||
- g_free (seat_id);
|
||||
-}
|
||||
-
|
||||
static const char *
|
||||
get_username_for_greeter_display (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
if (doing_initial_setup) {
|
||||
return INITIAL_SETUP_USERNAME;
|
||||
} else {
|
||||
return GDM_USERNAME;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_automatic_login_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
GdmSession *session;
|
||||
char *display_session_type = NULL;
|
||||
gboolean is_initial;
|
||||
|
||||
/* 0 is root user; since the daemon talks to the session object
|
||||
* directly, itself, for automatic login
|
||||
*/
|
||||
session = create_user_session_for_display (manager, display, 0);
|
||||
|
||||
@@ -1709,61 +1567,60 @@ on_display_status_changed (GdmDisplay *display,
|
||||
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
|
||||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
|
||||
char *session_class;
|
||||
|
||||
g_object_get (display,
|
||||
"session-class", &session_class,
|
||||
NULL);
|
||||
if (g_strcmp0 (session_class, "greeter") == 0)
|
||||
set_up_session (manager, display);
|
||||
g_free (session_class);
|
||||
}
|
||||
|
||||
if (status == GDM_DISPLAY_MANAGED) {
|
||||
greeter_display_started (manager, display);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
#ifdef WITH_PLYMOUTH
|
||||
if (quit_plymouth) {
|
||||
plymouth_quit_without_transition ();
|
||||
manager->priv->plymouth_is_running = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0) {
|
||||
manager->priv->ran_once = TRUE;
|
||||
}
|
||||
maybe_start_pending_initial_login (manager, display);
|
||||
- maybe_activate_other_session (manager, display);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
char *id;
|
||||
|
||||
gdm_display_get_id (display, &id, NULL);
|
||||
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
||||
g_free (id);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
|
||||
|
||||
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_start_user_session_operation (StartUserSessionOperation *operation)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (operation->session),
|
||||
"start-user-session-operation",
|
||||
NULL);
|
||||
g_object_unref (operation->session);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,87 @@
|
||||
From 299a0981f4e9fc02716d64abf5e5e692e2ad2951 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 3 Aug 2018 16:50:36 -0400
|
||||
Subject: [PATCH 13/51] local-display-factory: ensure non-seat0 codepath
|
||||
doesn't affect seat0
|
||||
|
||||
create_display currently bails in some cases if any display is running
|
||||
on the seat. That's the right thing to do on seats other than seat0,
|
||||
but wrong for seat0 (which an have multiple sessions at the same
|
||||
time).
|
||||
|
||||
To ensure we never hit the case for seat0, add a call to check if
|
||||
the passed seat is multi-session capable.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 0e454c880..7f7735ca1 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -373,61 +373,61 @@ lookup_by_seat_id (const char *id,
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
char *active_session_id = NULL;
|
||||
int ret;
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
char *login_session_id = NULL;
|
||||
|
||||
/* If we already have a login window, switch to it */
|
||||
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
}
|
||||
g_clear_pointer (&login_session_id, g_free);
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
return NULL;
|
||||
}
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
- } else {
|
||||
+ } else if (!sd_seat_can_multi_session (seat_id)) {
|
||||
/* Ensure we don't create the same display more than once */
|
||||
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
|
||||
if (display != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
|
||||
g_object_set (display, "seat-id", seat_id, NULL);
|
||||
g_object_set (display, "is-initial", initial, NULL);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,369 @@
|
||||
From 08f5f88ca6fb0edfc94af4c85912484b6048691b Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 2 Aug 2018 15:06:09 -0400
|
||||
Subject: [PATCH 14/51] daemon: kill and restart greeter on demand under
|
||||
wayland
|
||||
|
||||
Right now we leave the greeter alive after the user logs in.
|
||||
This is for two reasons:
|
||||
|
||||
1) When the greeter is running Xorg, there's no way to kill
|
||||
it when it's running on an inactive VT (X jumps to the foreground
|
||||
when being killed)
|
||||
|
||||
2) The greeter, in a way, provides a securepath for unlock.
|
||||
Users in theory could know that by hitting ctrl-alt-f1 to secure
|
||||
attention, the login screen presented is not spoofed.
|
||||
|
||||
Since we use wayland by default, 1 isn't that much of a concern,
|
||||
and 2 is a bit of niche feature that most users probably haven't
|
||||
considered.
|
||||
|
||||
And there's a huge downside to keeping the greeter alive: it uses
|
||||
a very large amount of memory.
|
||||
|
||||
This commit changes GDM to kill the login screen when switching
|
||||
away from the login screen's VT and restarting it when switching
|
||||
back.
|
||||
|
||||
Based heavily on work by Hans de Goede <hdegoede@redhat.com>
|
||||
|
||||
Closes: https://gitlab.gnome.org/GNOME/gdm/issues/222
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 167 +++++++++++++++++++++++++++++
|
||||
1 file changed, 167 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 7f7735ca1..4ae656ab3 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -34,60 +34,65 @@
|
||||
#include "gdm-manager.h"
|
||||
#include "gdm-display-factory.h"
|
||||
#include "gdm-local-display-factory.h"
|
||||
#include "gdm-local-display-factory-glue.h"
|
||||
|
||||
#include "gdm-settings-keys.h"
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-display-store.h"
|
||||
#include "gdm-local-display.h"
|
||||
#include "gdm-legacy-display.h"
|
||||
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
||||
|
||||
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
||||
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
||||
|
||||
#define MAX_DISPLAY_FAILURES 5
|
||||
|
||||
struct GdmLocalDisplayFactoryPrivate
|
||||
{
|
||||
GdmDBusLocalDisplayFactory *skeleton;
|
||||
GDBusConnection *connection;
|
||||
GHashTable *used_display_numbers;
|
||||
|
||||
/* FIXME: this needs to be per seat? */
|
||||
guint num_failures;
|
||||
|
||||
guint seat_new_id;
|
||||
guint seat_removed_id;
|
||||
+
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ char *tty_of_active_vt;
|
||||
+ guint active_vt_watch_id;
|
||||
+#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
};
|
||||
|
||||
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
|
||||
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
|
||||
static void gdm_local_display_factory_finalize (GObject *object);
|
||||
|
||||
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial_display);
|
||||
|
||||
static void on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory);
|
||||
|
||||
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
|
||||
static gpointer local_display_factory_object = NULL;
|
||||
|
||||
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
||||
|
||||
GQuark
|
||||
gdm_local_display_factory_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
if (ret == 0) {
|
||||
ret = g_quark_from_static_string ("gdm_local_display_factory_error");
|
||||
@@ -507,98 +512,260 @@ gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
|
||||
static void
|
||||
on_seat_new (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *seat;
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
create_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat, NULL, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
on_seat_removed (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *seat;
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
||||
}
|
||||
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+static gboolean
|
||||
+lookup_by_session_id (const char *id,
|
||||
+ GdmDisplay *display,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ const char *looking_for = user_data;
|
||||
+ const char *current;
|
||||
+
|
||||
+ current = gdm_display_get_session_id (display);
|
||||
+ return g_strcmp0 (current, looking_for) == 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+maybe_stop_greeter_display (GdmDisplay *display)
|
||||
+{
|
||||
+ g_autofree char *display_session_type = NULL;
|
||||
+
|
||||
+ if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
|
||||
+ return;
|
||||
+
|
||||
+ g_object_get (G_OBJECT (display),
|
||||
+ "session-type", &display_session_type,
|
||||
+ NULL);
|
||||
+
|
||||
+ /* we can only stop greeter for wayland sessions, since
|
||||
+ * X server would jump back on exit */
|
||||
+ if (g_strcmp0 (display_session_type, "wayland") != 0)
|
||||
+ return;
|
||||
+
|
||||
+ gdm_display_stop_greeter_session (display);
|
||||
+ gdm_display_unmanage (display);
|
||||
+ gdm_display_finish (display);
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+on_vt_changed (GIOChannel *source,
|
||||
+ GIOCondition condition,
|
||||
+ GdmLocalDisplayFactory *factory)
|
||||
+{
|
||||
+ GIOStatus status;
|
||||
+ static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
||||
+ g_autofree char *tty_of_previous_vt = NULL;
|
||||
+ g_autofree char *tty_of_active_vt = NULL;
|
||||
+ g_autofree char *login_session_id = NULL;
|
||||
+ g_autofree char *active_session_id = NULL;
|
||||
+ const char *session_type = NULL;
|
||||
+ int ret;
|
||||
+
|
||||
+ g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
||||
+
|
||||
+ if (condition & G_IO_PRI) {
|
||||
+ g_autoptr (GError) error = NULL;
|
||||
+ status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
||||
+
|
||||
+ if (error != NULL) {
|
||||
+ g_warning ("could not read active VT from kernel: %s", error->message);
|
||||
+ }
|
||||
+ switch (status) {
|
||||
+ case G_IO_STATUS_ERROR:
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+ case G_IO_STATUS_EOF:
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+ case G_IO_STATUS_AGAIN:
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+ case G_IO_STATUS_NORMAL:
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+
|
||||
+ if (tty_of_active_vt == NULL)
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+
|
||||
+ g_strchomp (tty_of_active_vt);
|
||||
+
|
||||
+ /* don't do anything if we're on the same VT we were before */
|
||||
+ if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0)
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+
|
||||
+ tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
|
||||
+ factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
|
||||
+
|
||||
+ /* if the old VT was running a wayland login screen kill it
|
||||
+ */
|
||||
+ if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
||||
+ unsigned int vt;
|
||||
+
|
||||
+ ret = sd_session_get_vt (login_session_id, &vt);
|
||||
+ if (ret == 0 && vt != 0) {
|
||||
+ g_autofree char *tty_of_login_window_vt = NULL;
|
||||
+
|
||||
+ tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
||||
+
|
||||
+ if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
+ GdmDisplayStore *store;
|
||||
+ GdmDisplay *display;
|
||||
+
|
||||
+ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
+ display = gdm_display_store_find (store,
|
||||
+ lookup_by_session_id,
|
||||
+ (gpointer) login_session_id);
|
||||
+
|
||||
+ if (display != NULL)
|
||||
+ maybe_stop_greeter_display (display);
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* if user jumped back to initial vt and it's empty put a login screen
|
||||
+ * on it (unless a login screen is already running elsewhere, then
|
||||
+ * jump to that login screen)
|
||||
+ */
|
||||
+ if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
+
|
||||
+ ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
||||
+
|
||||
+ if (ret == 0) {
|
||||
+ g_autofree char *state = NULL;
|
||||
+ ret = sd_session_get_state (active_session_id, &state);
|
||||
+
|
||||
+ /* if there's something already running on the active VT then bail */
|
||||
+ if (ret == 0 && g_strcmp0 (state, "closing") != 0)
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
+
|
||||
+ if (gdm_local_display_factory_use_wayland ())
|
||||
+ session_type = "wayland";
|
||||
+
|
||||
+ create_display (factory, "seat0", session_type, TRUE);
|
||||
+
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
static void
|
||||
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
+ g_autoptr (GIOChannel) io_channel = NULL;
|
||||
+
|
||||
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatNew",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_seat_new,
|
||||
g_object_ref (factory),
|
||||
g_object_unref);
|
||||
factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatRemoved",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_seat_removed,
|
||||
g_object_ref (factory),
|
||||
g_object_unref);
|
||||
+
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
|
||||
+
|
||||
+ if (io_channel != NULL) {
|
||||
+ factory->priv->active_vt_watch_id =
|
||||
+ g_io_add_watch (io_channel,
|
||||
+ G_IO_PRI,
|
||||
+ (GIOFunc)
|
||||
+ on_vt_changed,
|
||||
+ factory);
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
if (factory->priv->seat_new_id) {
|
||||
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
||||
factory->priv->seat_new_id);
|
||||
factory->priv->seat_new_id = 0;
|
||||
}
|
||||
if (factory->priv->seat_removed_id) {
|
||||
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
||||
factory->priv->seat_removed_id);
|
||||
factory->priv->seat_removed_id = 0;
|
||||
}
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ if (factory->priv->active_vt_watch_id) {
|
||||
+ g_source_remove (factory->priv->active_vt_watch_id);
|
||||
+ factory->priv->active_vt_watch_id = 0;
|
||||
+ }
|
||||
+
|
||||
+ g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
|
||||
+#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_added (GdmDisplayStore *display_store,
|
||||
const char *id,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_lookup (display_store, id);
|
||||
|
||||
if (display != NULL) {
|
||||
g_signal_connect_object (display, "notify::status",
|
||||
G_CALLBACK (on_display_status_changed),
|
||||
factory,
|
||||
0);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory);
|
||||
g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,235 @@
|
||||
From 59533722f1749d4e71360c5d717a18006c1f64c0 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 7 Aug 2018 13:55:06 -0400
|
||||
Subject: [PATCH 15/51] local-display-factory: add more debug messages to new
|
||||
vt handling code
|
||||
|
||||
commit c0188a7030 added some complex code for starting and stopping
|
||||
the login screen based on VT changes.
|
||||
|
||||
That code currently has zero debug statements in it making it trickier
|
||||
than necessary to debug.
|
||||
|
||||
This commit sprinkles some g_debug's throughout the function.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 44 ++++++++++++++++++++++++------
|
||||
1 file changed, 35 insertions(+), 9 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 4ae656ab3..2a2259f2a 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -530,175 +530,201 @@ on_seat_removed (GDBusConnection *connection,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *seat;
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
static gboolean
|
||||
lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
const char *current;
|
||||
|
||||
current = gdm_display_get_session_id (display);
|
||||
return g_strcmp0 (current, looking_for) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_stop_greeter_display (GdmDisplay *display)
|
||||
{
|
||||
g_autofree char *display_session_type = NULL;
|
||||
|
||||
- if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
|
||||
+ if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
||||
return;
|
||||
+ }
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"session-type", &display_session_type,
|
||||
NULL);
|
||||
|
||||
/* we can only stop greeter for wayland sessions, since
|
||||
* X server would jump back on exit */
|
||||
- if (g_strcmp0 (display_session_type, "wayland") != 0)
|
||||
+ if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
||||
return;
|
||||
+ }
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: killing login window since its now unused");
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_vt_changed (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GIOStatus status;
|
||||
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
||||
g_autofree char *tty_of_previous_vt = NULL;
|
||||
g_autofree char *tty_of_active_vt = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
g_autofree char *active_session_id = NULL;
|
||||
const char *session_type = NULL;
|
||||
int ret;
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: received VT change event");
|
||||
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
||||
|
||||
if (condition & G_IO_PRI) {
|
||||
g_autoptr (GError) error = NULL;
|
||||
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
||||
|
||||
if (error != NULL) {
|
||||
g_warning ("could not read active VT from kernel: %s", error->message);
|
||||
}
|
||||
switch (status) {
|
||||
case G_IO_STATUS_ERROR:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_EOF:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_AGAIN:
|
||||
return G_SOURCE_CONTINUE;
|
||||
case G_IO_STATUS_NORMAL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
- if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
|
||||
+ if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: kernel hung up active vt watch");
|
||||
return G_SOURCE_REMOVE;
|
||||
+ }
|
||||
|
||||
- if (tty_of_active_vt == NULL)
|
||||
+ if (tty_of_active_vt == NULL) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: unable to read active VT from kernel");
|
||||
return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
|
||||
g_strchomp (tty_of_active_vt);
|
||||
|
||||
- /* don't do anything if we're on the same VT we were before */
|
||||
- if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0)
|
||||
- return G_SOURCE_CONTINUE;
|
||||
-
|
||||
tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
|
||||
factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
|
||||
|
||||
+ /* don't do anything at start up */
|
||||
+ if (tty_of_previous_vt == NULL) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT is %s at startup",
|
||||
+ factory->priv->tty_of_active_vt);
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
+
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
||||
+ tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
||||
+
|
||||
/* if the old VT was running a wayland login screen kill it
|
||||
*/
|
||||
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
||||
unsigned int vt;
|
||||
|
||||
ret = sd_session_get_vt (login_session_id, &vt);
|
||||
if (ret == 0 && vt != 0) {
|
||||
g_autofree char *tty_of_login_window_vt = NULL;
|
||||
|
||||
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
||||
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display;
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
||||
+
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
|
||||
if (display != NULL)
|
||||
maybe_stop_greeter_display (display);
|
||||
+ } else {
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if user jumped back to initial vt and it's empty put a login screen
|
||||
* on it (unless a login screen is already running elsewhere, then
|
||||
* jump to that login screen)
|
||||
*/
|
||||
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
g_autofree char *state = NULL;
|
||||
ret = sd_session_get_state (active_session_id, &state);
|
||||
|
||||
/* if there's something already running on the active VT then bail */
|
||||
- if (ret == 0 && g_strcmp0 (state, "closing") != 0)
|
||||
+ if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
session_type = "wayland";
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
|
||||
+
|
||||
create_display (factory, "seat0", session_type, TRUE);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
g_autoptr (GIOChannel) io_channel = NULL;
|
||||
|
||||
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatNew",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_seat_new,
|
||||
g_object_ref (factory),
|
||||
g_object_unref);
|
||||
factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatRemoved",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_seat_removed,
|
||||
g_object_ref (factory),
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,97 @@
|
||||
From e5bf6d78ff8f54bbb74e572f05ccbf1c0df24017 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 7 Aug 2018 13:55:06 -0400
|
||||
Subject: [PATCH 16/51] local-display-factory: don't start two greeters at
|
||||
startup
|
||||
|
||||
commit c0188a7030 added some complex code for starting
|
||||
the login screen when the user switches to the initial
|
||||
VT if nothing is running on that VT.
|
||||
|
||||
The problem is, we get a VT change event on that VT as
|
||||
part of the start up process.
|
||||
|
||||
This leads to an additional greeter getting started.
|
||||
|
||||
This commit adds a check to side step the new code during
|
||||
startup.
|
||||
|
||||
Closes: https://gitlab.gnome.org/GNOME/gdm/issues/409
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 2a2259f2a..9f377ba9a 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -600,60 +600,66 @@ on_vt_changed (GIOChannel *source,
|
||||
g_autoptr (GError) error = NULL;
|
||||
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
||||
|
||||
if (error != NULL) {
|
||||
g_warning ("could not read active VT from kernel: %s", error->message);
|
||||
}
|
||||
switch (status) {
|
||||
case G_IO_STATUS_ERROR:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_EOF:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_AGAIN:
|
||||
return G_SOURCE_CONTINUE;
|
||||
case G_IO_STATUS_NORMAL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
|
||||
g_debug ("GdmLocalDisplayFactory: kernel hung up active vt watch");
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
if (tty_of_active_vt == NULL) {
|
||||
g_debug ("GdmLocalDisplayFactory: unable to read active VT from kernel");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
g_strchomp (tty_of_active_vt);
|
||||
|
||||
+ /* don't do anything if we're on the same VT we were before */
|
||||
+ if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT changed to the same VT, ignoring");
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
+
|
||||
tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
|
||||
factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
|
||||
|
||||
/* don't do anything at start up */
|
||||
if (tty_of_previous_vt == NULL) {
|
||||
g_debug ("GdmLocalDisplayFactory: VT is %s at startup",
|
||||
factory->priv->tty_of_active_vt);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
||||
tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
||||
|
||||
/* if the old VT was running a wayland login screen kill it
|
||||
*/
|
||||
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
||||
unsigned int vt;
|
||||
|
||||
ret = sd_session_get_vt (login_session_id, &vt);
|
||||
if (ret == 0 && vt != 0) {
|
||||
g_autofree char *tty_of_login_window_vt = NULL;
|
||||
|
||||
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
||||
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,128 @@
|
||||
From de4b24f63e62a39b2cb10a8c58c54d86559f7f26 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 7 Aug 2018 14:04:44 -0400
|
||||
Subject: [PATCH 17/51] session-worker: don't switch VTs if we're already on
|
||||
the right VT
|
||||
|
||||
commit 5b5dccbd shows that switching VTs to the same VT isn't
|
||||
exactly a no-op. In order to prevent unnecessary wakeups, avoid
|
||||
switching VTs if the worker is already on the correct VT.
|
||||
---
|
||||
daemon/gdm-session-worker.c | 22 ++++++++++++++++------
|
||||
1 file changed, 16 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index 0322037e0..fd6470bab 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -936,91 +936,101 @@ fix_terminal_vt_mode (GdmSessionWorker *worker,
|
||||
if (ioctl (tty_fd, KDGETMODE, &kernel_display_mode) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't query kernel display mode: %m");
|
||||
succeeded = FALSE;
|
||||
}
|
||||
|
||||
if (kernel_display_mode == KD_TEXT) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* VT is in the anti-social state of VT_AUTO + KD_GRAPHICS,
|
||||
* fix it.
|
||||
*/
|
||||
succeeded = handle_terminal_vt_switches (worker, tty_fd);
|
||||
mode_fixed = TRUE;
|
||||
out:
|
||||
if (!succeeded) {
|
||||
g_error ("GdmSessionWorker: couldn't set up terminal, aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("GdmSessionWorker: VT mode did %sneed to be fixed",
|
||||
mode_fixed? "" : "not ");
|
||||
}
|
||||
|
||||
static void
|
||||
jump_to_vt (GdmSessionWorker *worker,
|
||||
int vt_number)
|
||||
{
|
||||
int fd;
|
||||
int active_vt_tty_fd;
|
||||
+ int active_vt = -1;
|
||||
+ struct vt_stat vt_state = { 0 };
|
||||
|
||||
g_debug ("GdmSessionWorker: jumping to VT %d", vt_number);
|
||||
active_vt_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (worker->priv->session_tty_fd != -1) {
|
||||
fd = worker->priv->session_tty_fd;
|
||||
|
||||
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
|
||||
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
|
||||
}
|
||||
|
||||
/* It's possible that the current VT was left in a broken
|
||||
* combination of states (KD_GRAPHICS with VT_AUTO), that
|
||||
* can't be switched away from. This call makes sure things
|
||||
* are set in a way that VT_ACTIVATE should work and
|
||||
* VT_WAITACTIVE shouldn't hang.
|
||||
*/
|
||||
fix_terminal_vt_mode (worker, active_vt_tty_fd);
|
||||
} else {
|
||||
fd = active_vt_tty_fd;
|
||||
}
|
||||
|
||||
handle_terminal_vt_switches (worker, fd);
|
||||
|
||||
- if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
|
||||
- g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
|
||||
- vt_number);
|
||||
- } else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
|
||||
- g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
|
||||
- vt_number);
|
||||
+ if (ioctl (fd, VT_GETSTATE, &vt_state) <= 0) {
|
||||
+ g_debug ("GdmSessionWorker: couldn't get current VT: %m");
|
||||
+ } else {
|
||||
+ active_vt = vt_state.v_active;
|
||||
+ }
|
||||
+
|
||||
+ if (active_vt != vt_number) {
|
||||
+ if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
|
||||
+ g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
|
||||
+ vt_number);
|
||||
+ } else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
|
||||
+ g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
|
||||
+ vt_number);
|
||||
+ }
|
||||
}
|
||||
|
||||
close (active_vt_tty_fd);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_set_state (GdmSessionWorker *worker,
|
||||
GdmSessionWorkerState state)
|
||||
{
|
||||
if (worker->priv->state == state)
|
||||
return;
|
||||
|
||||
worker->priv->state = state;
|
||||
g_object_notify (G_OBJECT (worker), "state");
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
|
||||
int status)
|
||||
{
|
||||
g_debug ("GdmSessionWorker: uninitializing PAM");
|
||||
|
||||
if (worker->priv->pam_handle == NULL)
|
||||
return;
|
||||
|
||||
gdm_session_worker_get_username (worker, NULL);
|
||||
|
||||
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
|
||||
pam_close_session (worker->priv->pam_handle, 0);
|
||||
gdm_session_auditor_report_logout (worker->priv->auditor);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,87 @@
|
||||
From b9e5a2879a410b6a85be6c01c6f49cd7eb24c800 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 31 Aug 2018 15:20:39 -0400
|
||||
Subject: [PATCH 18/51] session-worker: fix current vt detection short-circuit
|
||||
logic
|
||||
|
||||
commit 8169cd4 attempts to avoid changing VTs if the active VT
|
||||
is the same as the VT getting jumped to.
|
||||
|
||||
It fails to work, however, because accidentally treats a 0 return
|
||||
code to the VT_GETSTATE ioctl as failure.
|
||||
|
||||
this commit fixes that.
|
||||
---
|
||||
daemon/gdm-session-worker.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index fd6470bab..391969d96 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -963,61 +963,61 @@ jump_to_vt (GdmSessionWorker *worker,
|
||||
{
|
||||
int fd;
|
||||
int active_vt_tty_fd;
|
||||
int active_vt = -1;
|
||||
struct vt_stat vt_state = { 0 };
|
||||
|
||||
g_debug ("GdmSessionWorker: jumping to VT %d", vt_number);
|
||||
active_vt_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (worker->priv->session_tty_fd != -1) {
|
||||
fd = worker->priv->session_tty_fd;
|
||||
|
||||
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
|
||||
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
|
||||
}
|
||||
|
||||
/* It's possible that the current VT was left in a broken
|
||||
* combination of states (KD_GRAPHICS with VT_AUTO), that
|
||||
* can't be switched away from. This call makes sure things
|
||||
* are set in a way that VT_ACTIVATE should work and
|
||||
* VT_WAITACTIVE shouldn't hang.
|
||||
*/
|
||||
fix_terminal_vt_mode (worker, active_vt_tty_fd);
|
||||
} else {
|
||||
fd = active_vt_tty_fd;
|
||||
}
|
||||
|
||||
handle_terminal_vt_switches (worker, fd);
|
||||
|
||||
- if (ioctl (fd, VT_GETSTATE, &vt_state) <= 0) {
|
||||
+ if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't get current VT: %m");
|
||||
} else {
|
||||
active_vt = vt_state.v_active;
|
||||
}
|
||||
|
||||
if (active_vt != vt_number) {
|
||||
if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
|
||||
vt_number);
|
||||
} else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
|
||||
vt_number);
|
||||
}
|
||||
}
|
||||
|
||||
close (active_vt_tty_fd);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_session_worker_set_state (GdmSessionWorker *worker,
|
||||
GdmSessionWorkerState state)
|
||||
{
|
||||
if (worker->priv->state == state)
|
||||
return;
|
||||
|
||||
worker->priv->state = state;
|
||||
g_object_notify (G_OBJECT (worker), "state");
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,168 @@
|
||||
From fe680d77cff9272843cb171c7e590c239f7afe5a Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 9 Aug 2018 12:32:31 -0400
|
||||
Subject: [PATCH 19/51] local-display-factory: don't jump to failed display
|
||||
|
||||
Since commit 5e737a57 `create_display` will jump to any
|
||||
already running login screen if it can find one.
|
||||
|
||||
Right now if a display fails we call `create_display` to
|
||||
create a new one. It will look for any already running
|
||||
login screen and find the recently failed display.
|
||||
|
||||
This commit make sure we never jump to a display that isn't
|
||||
in good working order.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 19 +++++++++++++++----
|
||||
1 file changed, 15 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 9f377ba9a..c58de9c17 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -60,60 +60,63 @@ struct GdmLocalDisplayFactoryPrivate
|
||||
guint num_failures;
|
||||
|
||||
guint seat_new_id;
|
||||
guint seat_removed_id;
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
char *tty_of_active_vt;
|
||||
guint active_vt_watch_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
};
|
||||
|
||||
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
|
||||
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
|
||||
static void gdm_local_display_factory_finalize (GObject *object);
|
||||
|
||||
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial_display);
|
||||
|
||||
static void on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory);
|
||||
|
||||
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
|
||||
static gpointer local_display_factory_object = NULL;
|
||||
+static gboolean lookup_by_session_id (const char *id,
|
||||
+ GdmDisplay *display,
|
||||
+ gpointer user_data);
|
||||
|
||||
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
||||
|
||||
GQuark
|
||||
gdm_local_display_factory_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
if (ret == 0) {
|
||||
ret = g_quark_from_static_string ("gdm_local_display_factory_error");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
listify_hash (gpointer key,
|
||||
GdmDisplay *display,
|
||||
GList **list)
|
||||
{
|
||||
*list = g_list_prepend (*list, key);
|
||||
}
|
||||
|
||||
static int
|
||||
sort_nums (gpointer a,
|
||||
gpointer b)
|
||||
{
|
||||
guint32 num_a;
|
||||
guint32 num_b;
|
||||
|
||||
num_a = GPOINTER_TO_UINT (a);
|
||||
@@ -370,66 +373,74 @@ lookup_by_seat_id (const char *id,
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
||||
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
char *active_session_id = NULL;
|
||||
int ret;
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
char *login_session_id = NULL;
|
||||
|
||||
/* If we already have a login window, switch to it */
|
||||
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
- if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
- gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
+ GdmDisplay *display;
|
||||
+
|
||||
+ display = gdm_display_store_find (store,
|
||||
+ lookup_by_session_id,
|
||||
+ (gpointer) login_session_id);
|
||||
+ if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
+ if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
+ gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
+ }
|
||||
+ g_clear_pointer (&login_session_id, g_free);
|
||||
+ g_clear_pointer (&active_session_id, g_free);
|
||||
+ return NULL;
|
||||
}
|
||||
g_clear_pointer (&login_session_id, g_free);
|
||||
- g_clear_pointer (&active_session_id, g_free);
|
||||
- return NULL;
|
||||
}
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
} else if (!sd_seat_can_multi_session (seat_id)) {
|
||||
/* Ensure we don't create the same display more than once */
|
||||
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
|
||||
if (display != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,161 @@
|
||||
From 94207dd5699f1cd2fe7d516c20e1de2b2e2778fb Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 9 Aug 2018 12:48:25 -0400
|
||||
Subject: [PATCH 20/51] local-display-factory: add some more debug statements
|
||||
|
||||
This commit just sprinkles in a few more `g_debug`'s for
|
||||
log file clarity.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 5 +++++
|
||||
1 file changed, 5 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index c58de9c17..6f3a4c391 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -364,76 +364,80 @@ on_display_status_changed (GdmDisplay *display,
|
||||
|
||||
static gboolean
|
||||
lookup_by_seat_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
char *current;
|
||||
gboolean res;
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
||||
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
char *active_session_id = NULL;
|
||||
int ret;
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
|
||||
+ session_type? : "X11", seat_id);
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
char *login_session_id = NULL;
|
||||
|
||||
/* If we already have a login window, switch to it */
|
||||
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
|
||||
+ login_session_id);
|
||||
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
}
|
||||
g_clear_pointer (&login_session_id, g_free);
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
return NULL;
|
||||
}
|
||||
g_clear_pointer (&login_session_id, g_free);
|
||||
}
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
} else if (!sd_seat_can_multi_session (seat_id)) {
|
||||
/* Ensure we don't create the same display more than once */
|
||||
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
|
||||
if (display != NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
@@ -453,60 +457,61 @@ create_display (GdmLocalDisplayFactory *factory,
|
||||
g_object_unref (display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
gdm_display_unmanage (display);
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id) {
|
||||
|
||||
GdmDisplayStore *store;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Removing used_display_numbers on seat %s", seat_id);
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *result;
|
||||
GVariant *array;
|
||||
GVariantIter iter;
|
||||
const char *seat;
|
||||
|
||||
+ g_debug ("GdmLocalDisplayFactory: enumerating seats from logind");
|
||||
result = g_dbus_connection_call_sync (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"/org/freedesktop/login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"ListSeats",
|
||||
NULL,
|
||||
G_VARIANT_TYPE ("(a(so))"),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL, &error);
|
||||
|
||||
if (!result) {
|
||||
g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error->message);
|
||||
g_clear_error (&error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
array = g_variant_get_child_value (result, 0);
|
||||
g_variant_iter_init (&iter, array);
|
||||
|
||||
while (g_variant_iter_loop (&iter, "(&so)", &seat, NULL)) {
|
||||
gboolean is_initial;
|
||||
const char *session_type = NULL;
|
||||
|
||||
if (g_strcmp0 (seat, "seat0") == 0) {
|
||||
is_initial = TRUE;
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
session_type = "wayland";
|
||||
} else {
|
||||
is_initial = FALSE;
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,162 @@
|
||||
From abd8e1ef71d093a3ab5c110aea5fa2012d59d5e2 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 14 Aug 2018 10:21:17 -0400
|
||||
Subject: [PATCH 21/51] local-display-factory: ignore spurios SeatNew signal at
|
||||
start up
|
||||
|
||||
Sometimes during startup, logind will send a `SeatNew` signal for
|
||||
seat0 after GDM has already called `ListSeats` and processed `seat0`.
|
||||
|
||||
That `SeatNew` signal leads to GDM calling `create_display` twice in
|
||||
quick succession.
|
||||
|
||||
This commit changes GDM to avoid such double processing, by ignoring
|
||||
the `create_display` requests for seats that already have a prepared
|
||||
display ("prepared" means "starting up").
|
||||
|
||||
Closes: https://gitlab.gnome.org/GNOME/gdm/issues/410
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 33 +++++++++++++++++++++++-------
|
||||
1 file changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 6f3a4c391..127127005 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -353,107 +353,126 @@ on_display_status_changed (GdmDisplay *display,
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
g_free (session_type);
|
||||
g_free (session_class);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_by_seat_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
char *current;
|
||||
gboolean res;
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
||||
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+lookup_prepared_display_by_seat_id (const char *id,
|
||||
+ GdmDisplay *display,
|
||||
+ gpointer user_data)
|
||||
+{
|
||||
+ int status;
|
||||
+
|
||||
+ status = gdm_display_get_status (display);
|
||||
+
|
||||
+ if (status != GDM_DISPLAY_PREPARED)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ return lookup_by_seat_id (id, display, user_data);
|
||||
+}
|
||||
+
|
||||
static GdmDisplay *
|
||||
create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
char *active_session_id = NULL;
|
||||
int ret;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
|
||||
session_type? : "X11", seat_id);
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
+ if (sd_seat_can_multi_session (seat_id))
|
||||
+ display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
|
||||
+ else
|
||||
+ display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
+
|
||||
+ /* Ensure we don't create the same display more than once */
|
||||
+ if (display != NULL) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: display already created");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
char *login_session_id = NULL;
|
||||
|
||||
/* If we already have a login window, switch to it */
|
||||
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
|
||||
login_session_id);
|
||||
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
}
|
||||
g_clear_pointer (&login_session_id, g_free);
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
return NULL;
|
||||
}
|
||||
g_clear_pointer (&login_session_id, g_free);
|
||||
}
|
||||
g_clear_pointer (&active_session_id, g_free);
|
||||
- } else if (!sd_seat_can_multi_session (seat_id)) {
|
||||
- /* Ensure we don't create the same display more than once */
|
||||
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
-
|
||||
- if (display != NULL) {
|
||||
- return NULL;
|
||||
- }
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
|
||||
g_object_set (display, "seat-id", seat_id, NULL);
|
||||
g_object_set (display, "is-initial", initial, NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
/* let store own the ref */
|
||||
g_object_unref (display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
--
|
||||
2.27.0
|
||||
|
91
SOURCES/0022-common-remove-unnecessary-free.patch
Normal file
91
SOURCES/0022-common-remove-unnecessary-free.patch
Normal file
@ -0,0 +1,91 @@
|
||||
From 9b8c21080286f943d0a19431bc8c0061f4833443 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 30 Aug 2018 13:04:56 -0400
|
||||
Subject: [PATCH 22/51] common: remove unnecessary free
|
||||
|
||||
This commit drops an erroneous free call, that would
|
||||
potentially free a dangling pointer.
|
||||
|
||||
Luckily the error condition can never occur because the
|
||||
error code checked is never returned, so the free call
|
||||
is dead code.
|
||||
|
||||
This commit removes the free call. A subsequent commit
|
||||
will fix the error code checking.
|
||||
---
|
||||
common/gdm-common.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/common/gdm-common.c b/common/gdm-common.c
|
||||
index 59317a889..c909aceee 100644
|
||||
--- a/common/gdm-common.c
|
||||
+++ b/common/gdm-common.c
|
||||
@@ -391,64 +391,62 @@ gdm_activate_session_by_id (GDBusConnection *connection,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_get_login_window_session_id (const char *seat_id,
|
||||
char **session_id)
|
||||
{
|
||||
gboolean ret;
|
||||
int res, i;
|
||||
char **sessions;
|
||||
char *service_id;
|
||||
char *service_class;
|
||||
char *state;
|
||||
|
||||
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
||||
if (res < 0) {
|
||||
g_debug ("Failed to determine sessions: %s", strerror (-res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sessions == NULL || sessions[0] == NULL) {
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
|
||||
res = sd_session_get_class (sessions[i], &service_class);
|
||||
if (res < 0) {
|
||||
- if (res == -ENOENT) {
|
||||
- free (service_class);
|
||||
+ if (res == -ENOENT)
|
||||
continue;
|
||||
- }
|
||||
|
||||
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_class, "greeter") != 0) {
|
||||
free (service_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
free (service_class);
|
||||
|
||||
ret = sd_session_get_state (sessions[i], &state);
|
||||
if (ret < 0) {
|
||||
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (state, "closing") == 0) {
|
||||
free (state);
|
||||
continue;
|
||||
}
|
||||
free (state);
|
||||
|
||||
res = sd_session_get_service (sessions[i], &service_id);
|
||||
if (res < 0) {
|
||||
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,133 @@
|
||||
From 4a948e4b203fdf5fcd9b5e53dd4a80ef2786c0cd Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 30 Aug 2018 13:06:54 -0400
|
||||
Subject: [PATCH 23/51] common: don't bail if session disappears out from under
|
||||
us
|
||||
|
||||
It's entirely possible for a session returned by
|
||||
sd_seat_get_sessions to disappear immediately after the
|
||||
sd_seat_get_sessions call returns. This is especially
|
||||
likely at logout time where the session will briefly be
|
||||
in the "closing" state before getting reaped.
|
||||
|
||||
If that happens when we're looking for a greeter session, we
|
||||
stop looking for a greeter session and bail out all confused.
|
||||
|
||||
This commit fixes the confusion by gracefully handling the
|
||||
session disappearing by just proceeding to the next session
|
||||
in the list.
|
||||
|
||||
This commit is very similar to commit 155ee7eca which got
|
||||
accidentally reverted during code consolidation. The main
|
||||
difference is this commit checks the correct error code
|
||||
of -ENXIO instead of -ENOENT, so it might actually fix
|
||||
what it's ostensibly supposed to fix.
|
||||
---
|
||||
common/gdm-common.c | 8 +++++++-
|
||||
1 file changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/common/gdm-common.c b/common/gdm-common.c
|
||||
index c909aceee..59b8dfc44 100644
|
||||
--- a/common/gdm-common.c
|
||||
+++ b/common/gdm-common.c
|
||||
@@ -391,90 +391,96 @@ gdm_activate_session_by_id (GDBusConnection *connection,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_get_login_window_session_id (const char *seat_id,
|
||||
char **session_id)
|
||||
{
|
||||
gboolean ret;
|
||||
int res, i;
|
||||
char **sessions;
|
||||
char *service_id;
|
||||
char *service_class;
|
||||
char *state;
|
||||
|
||||
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
|
||||
if (res < 0) {
|
||||
g_debug ("Failed to determine sessions: %s", strerror (-res));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (sessions == NULL || sessions[0] == NULL) {
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
|
||||
res = sd_session_get_class (sessions[i], &service_class);
|
||||
if (res < 0) {
|
||||
- if (res == -ENOENT)
|
||||
+ if (res == -ENXIO)
|
||||
continue;
|
||||
|
||||
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_class, "greeter") != 0) {
|
||||
free (service_class);
|
||||
continue;
|
||||
}
|
||||
|
||||
free (service_class);
|
||||
|
||||
ret = sd_session_get_state (sessions[i], &state);
|
||||
if (ret < 0) {
|
||||
+ if (res == -ENXIO)
|
||||
+ continue;
|
||||
+
|
||||
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (g_strcmp0 (state, "closing") == 0) {
|
||||
free (state);
|
||||
continue;
|
||||
}
|
||||
free (state);
|
||||
|
||||
res = sd_session_get_service (sessions[i], &service_id);
|
||||
if (res < 0) {
|
||||
+ if (res == -ENXIO)
|
||||
+ continue;
|
||||
+
|
||||
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
|
||||
ret = FALSE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (strcmp (service_id, "gdm-launch-environment") == 0) {
|
||||
*session_id = g_strdup (sessions[i]);
|
||||
ret = TRUE;
|
||||
|
||||
free (service_id);
|
||||
goto out;
|
||||
}
|
||||
|
||||
free (service_id);
|
||||
}
|
||||
|
||||
*session_id = NULL;
|
||||
ret = FALSE;
|
||||
|
||||
out:
|
||||
if (sessions) {
|
||||
for (i = 0; sessions[i]; i ++) {
|
||||
free (sessions[i]);
|
||||
}
|
||||
|
||||
free (sessions);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
138
SOURCES/0024-manager-better-logind-handling.patch
Normal file
138
SOURCES/0024-manager-better-logind-handling.patch
Normal file
@ -0,0 +1,138 @@
|
||||
From fac23cfa3e8e9fe21563733c0c1b739ddecead8a Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 30 Aug 2018 14:01:55 -0400
|
||||
Subject: [PATCH 24/51] manager: better logind handling
|
||||
|
||||
commit 9ee68d5c8 highlights we've incorrectly
|
||||
used ENOENT instead of ENXIO when checking for
|
||||
non-existing sessions/seats with logind.
|
||||
|
||||
This commit mops up all the other cases.
|
||||
---
|
||||
daemon/gdm-manager.c | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 80f60d24c..367a731cc 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -361,113 +361,113 @@ find_session_for_user_on_seat (GdmManager *manager,
|
||||
candidate_username);
|
||||
|
||||
if (g_strcmp0 (candidate_username, username) == 0 &&
|
||||
g_strcmp0 (candidate_seat_id, seat_id) == 0) {
|
||||
g_debug ("GdmManager: yes, found session %s", candidate_session_id);
|
||||
return candidate_session;
|
||||
}
|
||||
|
||||
g_debug ("GdmManager: no, will not use session %s", candidate_session_id);
|
||||
}
|
||||
|
||||
g_debug ("GdmManager: no matching sessions found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_remote_session (GdmManager *self,
|
||||
const char *session_id,
|
||||
GError **error)
|
||||
{
|
||||
char *seat;
|
||||
int ret;
|
||||
gboolean is_remote;
|
||||
|
||||
/* FIXME: The next release of logind is going to have explicit api for
|
||||
* checking remoteness.
|
||||
*/
|
||||
seat = NULL;
|
||||
ret = sd_session_get_seat (session_id, &seat);
|
||||
|
||||
- if (ret < 0 && ret != -ENOENT) {
|
||||
+ if (ret < 0 && ret != -ENXIO) {
|
||||
g_debug ("GdmManager: Error while retrieving seat for session %s: %s",
|
||||
session_id, strerror (-ret));
|
||||
}
|
||||
|
||||
if (seat != NULL) {
|
||||
is_remote = FALSE;
|
||||
free (seat);
|
||||
} else {
|
||||
is_remote = TRUE;
|
||||
}
|
||||
|
||||
return is_remote;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_seat_id_for_session_id (const char *session_id,
|
||||
GError **error)
|
||||
{
|
||||
int ret;
|
||||
char *seat, *out_seat;
|
||||
|
||||
seat = NULL;
|
||||
ret = sd_session_get_seat (session_id, &seat);
|
||||
|
||||
- if (ret == -ENOENT) {
|
||||
+ if (ret == -ENXIO) {
|
||||
out_seat = NULL;
|
||||
} else if (ret < 0) {
|
||||
g_set_error (error,
|
||||
GDM_DISPLAY_ERROR,
|
||||
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
|
||||
"Error getting uid for session id %s from systemd: %s",
|
||||
session_id,
|
||||
g_strerror (-ret));
|
||||
out_seat = NULL;
|
||||
} else {
|
||||
out_seat = g_strdup (seat);
|
||||
free (seat);
|
||||
}
|
||||
|
||||
return out_seat;
|
||||
}
|
||||
|
||||
static char *
|
||||
get_tty_for_session_id (const char *session_id,
|
||||
GError **error)
|
||||
{
|
||||
int ret;
|
||||
char *tty, *out_tty;
|
||||
|
||||
ret = sd_session_get_tty (session_id, &tty);
|
||||
|
||||
- if (ret == -ENOENT) {
|
||||
+ if (ret == -ENXIO) {
|
||||
out_tty = NULL;
|
||||
} else if (ret < 0) {
|
||||
g_set_error (error,
|
||||
GDM_DISPLAY_ERROR,
|
||||
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
|
||||
"Error getting tty for session id %s from systemd: %s",
|
||||
session_id,
|
||||
g_strerror (-ret));
|
||||
out_tty = NULL;
|
||||
} else {
|
||||
out_tty = g_strdup (tty);
|
||||
free (tty);
|
||||
}
|
||||
|
||||
return out_tty;
|
||||
}
|
||||
|
||||
static void
|
||||
get_display_and_details_for_bus_sender (GdmManager *self,
|
||||
GDBusConnection *connection,
|
||||
const char *sender,
|
||||
GdmDisplay **out_display,
|
||||
char **out_seat_id,
|
||||
char **out_session_id,
|
||||
char **out_tty,
|
||||
GPid *out_pid,
|
||||
uid_t *out_uid,
|
||||
gboolean *out_is_login_screen,
|
||||
gboolean *out_is_remote)
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,90 @@
|
||||
From cabcd21c17ca98e517a3eea7c9d5ce269445e3e0 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 31 Aug 2018 15:46:55 -0400
|
||||
Subject: [PATCH 25/51] session-worker: clear VT before jumping to it
|
||||
|
||||
If we're going to jump to a new VT we should make sure it's free
|
||||
of residual console text. That way if there's flicker the user
|
||||
will be less likely to notice it.
|
||||
|
||||
This commit sends a clear screen escape sequence to the tty
|
||||
before jumping to it.
|
||||
---
|
||||
daemon/gdm-session-worker.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index 391969d96..7ed2789da 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -943,60 +943,67 @@ fix_terminal_vt_mode (GdmSessionWorker *worker,
|
||||
}
|
||||
|
||||
/* VT is in the anti-social state of VT_AUTO + KD_GRAPHICS,
|
||||
* fix it.
|
||||
*/
|
||||
succeeded = handle_terminal_vt_switches (worker, tty_fd);
|
||||
mode_fixed = TRUE;
|
||||
out:
|
||||
if (!succeeded) {
|
||||
g_error ("GdmSessionWorker: couldn't set up terminal, aborting...");
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("GdmSessionWorker: VT mode did %sneed to be fixed",
|
||||
mode_fixed? "" : "not ");
|
||||
}
|
||||
|
||||
static void
|
||||
jump_to_vt (GdmSessionWorker *worker,
|
||||
int vt_number)
|
||||
{
|
||||
int fd;
|
||||
int active_vt_tty_fd;
|
||||
int active_vt = -1;
|
||||
struct vt_stat vt_state = { 0 };
|
||||
|
||||
g_debug ("GdmSessionWorker: jumping to VT %d", vt_number);
|
||||
active_vt_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (worker->priv->session_tty_fd != -1) {
|
||||
+ static const char *clear_screen_escape_sequence = "\33[H\33[2J";
|
||||
+
|
||||
+ /* let's make sure the new VT is clear */
|
||||
+ write (worker->priv->session_tty_fd,
|
||||
+ clear_screen_escape_sequence,
|
||||
+ sizeof (clear_screen_escape_sequence));
|
||||
+
|
||||
fd = worker->priv->session_tty_fd;
|
||||
|
||||
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
|
||||
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
|
||||
}
|
||||
|
||||
/* It's possible that the current VT was left in a broken
|
||||
* combination of states (KD_GRAPHICS with VT_AUTO), that
|
||||
* can't be switched away from. This call makes sure things
|
||||
* are set in a way that VT_ACTIVATE should work and
|
||||
* VT_WAITACTIVE shouldn't hang.
|
||||
*/
|
||||
fix_terminal_vt_mode (worker, active_vt_tty_fd);
|
||||
} else {
|
||||
fd = active_vt_tty_fd;
|
||||
}
|
||||
|
||||
handle_terminal_vt_switches (worker, fd);
|
||||
|
||||
if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't get current VT: %m");
|
||||
} else {
|
||||
active_vt = vt_state.v_active;
|
||||
}
|
||||
|
||||
if (active_vt != vt_number) {
|
||||
if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
|
||||
vt_number);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,133 @@
|
||||
From b773eb570d8c5f9d2222ee39eecbc6a622d108d8 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 30 Aug 2018 16:04:41 -0400
|
||||
Subject: [PATCH 26/51] manager: don't set ran_once after running initial-setup
|
||||
|
||||
GdmManager tracks whether or not the user session has ran
|
||||
once, so it won't autologin a user again after logout.
|
||||
|
||||
Unfortunately the initial-setup session was counting toward the
|
||||
ran_once count preventing initial-setup from logging the user
|
||||
in afterward.
|
||||
|
||||
This commit prevents ran_once from getting set in that case.
|
||||
---
|
||||
daemon/gdm-manager.c | 4 +++-
|
||||
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 367a731cc..c8197a043 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1519,105 +1519,107 @@ set_up_session (GdmManager *manager,
|
||||
operation->username = username;
|
||||
|
||||
g_signal_connect (user,
|
||||
"notify::is-loaded",
|
||||
G_CALLBACK (on_user_is_loaded_changed),
|
||||
operation);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
greeter_display_started (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
if (manager->priv->ran_once) {
|
||||
return;
|
||||
}
|
||||
|
||||
maybe_start_pending_initial_login (manager, display);
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmManager *manager)
|
||||
{
|
||||
int status;
|
||||
int display_number = -1;
|
||||
char *session_type = NULL;
|
||||
#ifdef WITH_PLYMOUTH
|
||||
gboolean display_is_local = FALSE;
|
||||
+ gboolean doing_initial_setup = FALSE;
|
||||
gboolean quit_plymouth = FALSE;
|
||||
|
||||
g_object_get (display,
|
||||
"is-local", &display_is_local,
|
||||
+ "doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
quit_plymouth = display_is_local && manager->priv->plymouth_is_running;
|
||||
#endif
|
||||
|
||||
g_object_get (display,
|
||||
"x11-display-number", &display_number,
|
||||
"session-type", &session_type,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
|
||||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
|
||||
char *session_class;
|
||||
|
||||
g_object_get (display,
|
||||
"session-class", &session_class,
|
||||
NULL);
|
||||
if (g_strcmp0 (session_class, "greeter") == 0)
|
||||
set_up_session (manager, display);
|
||||
g_free (session_class);
|
||||
}
|
||||
|
||||
if (status == GDM_DISPLAY_MANAGED) {
|
||||
greeter_display_started (manager, display);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
#ifdef WITH_PLYMOUTH
|
||||
if (quit_plymouth) {
|
||||
plymouth_quit_without_transition ();
|
||||
manager->priv->plymouth_is_running = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
- if (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0) {
|
||||
+ if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
|
||||
manager->priv->ran_once = TRUE;
|
||||
}
|
||||
maybe_start_pending_initial_login (manager, display);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
char *id;
|
||||
|
||||
gdm_display_get_id (display, &id, NULL);
|
||||
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
||||
g_free (id);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
|
||||
|
||||
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_start_user_session_operation (StartUserSessionOperation *operation)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (operation->session),
|
||||
--
|
||||
2.27.0
|
||||
|
418
SOURCES/0027-manager-start-initial-setup-right-away.patch
Normal file
418
SOURCES/0027-manager-start-initial-setup-right-away.patch
Normal file
@ -0,0 +1,418 @@
|
||||
From 3d4199f82136e7046b5b08fc7c583e3fce2d04a2 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 31 Aug 2018 14:33:58 -0400
|
||||
Subject: [PATCH 27/51] manager: start initial setup right away
|
||||
|
||||
We no longer restart the greeter as soon as it dies, since we
|
||||
start the greeter on demand. This means, we no longer need to
|
||||
defer starting initial setup until after the greeter respawns.
|
||||
|
||||
Furthermore, it doesn't work anymore since it relied on the
|
||||
respawn to trigger.
|
||||
|
||||
This commit removes that code and scaffolding and just starts
|
||||
initial setup directly.
|
||||
|
||||
https://gitlab.gnome.org/GNOME/gdm/issues/415
|
||||
---
|
||||
daemon/gdm-manager.c | 66 +-------------------------------------------
|
||||
1 file changed, 1 insertion(+), 65 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index c8197a043..fb7b1ec4b 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -62,62 +62,60 @@
|
||||
#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
|
||||
|
||||
#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdmManager *manager;
|
||||
GdmSession *session;
|
||||
char *service_name;
|
||||
guint idle_id;
|
||||
} StartUserSessionOperation;
|
||||
|
||||
struct GdmManagerPrivate
|
||||
{
|
||||
GdmDisplayStore *display_store;
|
||||
GdmLocalDisplayFactory *local_factory;
|
||||
#ifdef HAVE_LIBXDMCP
|
||||
GdmXdmcpDisplayFactory *xdmcp_factory;
|
||||
#endif
|
||||
GList *user_sessions;
|
||||
GHashTable *transient_sessions;
|
||||
GHashTable *open_reauthentication_requests;
|
||||
gboolean xdmcp_enabled;
|
||||
|
||||
gboolean started;
|
||||
gboolean show_local_greeter;
|
||||
|
||||
GDBusConnection *connection;
|
||||
GDBusObjectManagerServer *object_manager;
|
||||
|
||||
- StartUserSessionOperation *initial_login_operation;
|
||||
-
|
||||
#ifdef WITH_PLYMOUTH
|
||||
guint plymouth_is_running : 1;
|
||||
#endif
|
||||
guint ran_once : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_XDMCP_ENABLED,
|
||||
PROP_SHOW_LOCAL_GREETER
|
||||
};
|
||||
|
||||
enum {
|
||||
DISPLAY_ADDED,
|
||||
DISPLAY_REMOVED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SESSION_RECORD_LOGIN,
|
||||
SESSION_RECORD_LOGOUT,
|
||||
SESSION_RECORD_FAILED,
|
||||
} SessionRecord;
|
||||
|
||||
static guint signals [LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void gdm_manager_class_init (GdmManagerClass *klass);
|
||||
static void gdm_manager_init (GdmManager *manager);
|
||||
static void gdm_manager_dispose (GObject *object);
|
||||
|
||||
@@ -1286,96 +1284,60 @@ get_automatic_login_details (GdmManager *manager,
|
||||
if (res && enabled) {
|
||||
res = gdm_settings_direct_get_string (GDM_KEY_AUTO_LOGIN_USER, &username);
|
||||
}
|
||||
|
||||
if (enabled && res && username != NULL && username[0] != '\0') {
|
||||
goto out;
|
||||
}
|
||||
|
||||
g_free (username);
|
||||
username = NULL;
|
||||
enabled = FALSE;
|
||||
|
||||
out:
|
||||
if (enabled) {
|
||||
g_debug ("GdmDisplay: Got automatic login details for display: %d %s",
|
||||
enabled,
|
||||
username);
|
||||
} else {
|
||||
g_debug ("GdmDisplay: Got automatic login details for display: 0");
|
||||
}
|
||||
|
||||
if (usernamep != NULL) {
|
||||
*usernamep = username;
|
||||
} else {
|
||||
g_free (username);
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
-static void
|
||||
-maybe_start_pending_initial_login (GdmManager *manager,
|
||||
- GdmDisplay *greeter_display)
|
||||
-{
|
||||
- StartUserSessionOperation *operation;
|
||||
- char *greeter_seat_id = NULL;
|
||||
- char *user_session_seat_id = NULL;
|
||||
-
|
||||
- /* There may be a user session waiting to be started.
|
||||
- * This would happen if we couldn't start it earlier because
|
||||
- * the login screen X server was coming up and two X servers
|
||||
- * can't be started on the same seat at the same time.
|
||||
- */
|
||||
-
|
||||
- if (manager->priv->initial_login_operation == NULL) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- operation = manager->priv->initial_login_operation;
|
||||
-
|
||||
- g_object_get (G_OBJECT (greeter_display),
|
||||
- "seat-id", &greeter_seat_id,
|
||||
- NULL);
|
||||
- g_object_get (G_OBJECT (operation->session),
|
||||
- "display-seat-id", &user_session_seat_id,
|
||||
- NULL);
|
||||
-
|
||||
- if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) {
|
||||
- start_user_session (manager, operation);
|
||||
- manager->priv->initial_login_operation = NULL;
|
||||
- }
|
||||
-
|
||||
- g_free (greeter_seat_id);
|
||||
- g_free (user_session_seat_id);
|
||||
-}
|
||||
-
|
||||
static const char *
|
||||
get_username_for_greeter_display (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
if (doing_initial_setup) {
|
||||
return INITIAL_SETUP_USERNAME;
|
||||
} else {
|
||||
return GDM_USERNAME;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_automatic_login_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
GdmSession *session;
|
||||
char *display_session_type = NULL;
|
||||
gboolean is_initial;
|
||||
|
||||
/* 0 is root user; since the daemon talks to the session object
|
||||
* directly, itself, for automatic login
|
||||
*/
|
||||
session = create_user_session_for_display (manager, display, 0);
|
||||
|
||||
@@ -1498,131 +1460,115 @@ set_up_session (GdmManager *manager,
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
set_up_greeter_session (manager, display);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether the user really exists before committing to autologin. */
|
||||
user_manager = act_user_manager_get_default ();
|
||||
user = act_user_manager_get_user (user_manager, username);
|
||||
g_object_get (user_manager, "is-loaded", &loaded, NULL);
|
||||
|
||||
if (loaded) {
|
||||
set_up_automatic_login_session_if_user_exists (manager, display, user);
|
||||
} else {
|
||||
UsernameLookupOperation *operation;
|
||||
|
||||
operation = g_new (UsernameLookupOperation, 1);
|
||||
operation->manager = g_object_ref (manager);
|
||||
operation->display = g_object_ref (display);
|
||||
operation->username = username;
|
||||
|
||||
g_signal_connect (user,
|
||||
"notify::is-loaded",
|
||||
G_CALLBACK (on_user_is_loaded_changed),
|
||||
operation);
|
||||
}
|
||||
}
|
||||
|
||||
-static void
|
||||
-greeter_display_started (GdmManager *manager,
|
||||
- GdmDisplay *display)
|
||||
-{
|
||||
- if (manager->priv->ran_once) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- maybe_start_pending_initial_login (manager, display);
|
||||
-}
|
||||
-
|
||||
static void
|
||||
on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmManager *manager)
|
||||
{
|
||||
int status;
|
||||
int display_number = -1;
|
||||
char *session_type = NULL;
|
||||
#ifdef WITH_PLYMOUTH
|
||||
gboolean display_is_local = FALSE;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
gboolean quit_plymouth = FALSE;
|
||||
|
||||
g_object_get (display,
|
||||
"is-local", &display_is_local,
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
quit_plymouth = display_is_local && manager->priv->plymouth_is_running;
|
||||
#endif
|
||||
|
||||
g_object_get (display,
|
||||
"x11-display-number", &display_number,
|
||||
"session-type", &session_type,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
|
||||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
|
||||
char *session_class;
|
||||
|
||||
g_object_get (display,
|
||||
"session-class", &session_class,
|
||||
NULL);
|
||||
if (g_strcmp0 (session_class, "greeter") == 0)
|
||||
set_up_session (manager, display);
|
||||
g_free (session_class);
|
||||
}
|
||||
-
|
||||
- if (status == GDM_DISPLAY_MANAGED) {
|
||||
- greeter_display_started (manager, display);
|
||||
- }
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
#ifdef WITH_PLYMOUTH
|
||||
if (quit_plymouth) {
|
||||
plymouth_quit_without_transition ();
|
||||
manager->priv->plymouth_is_running = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
|
||||
manager->priv->ran_once = TRUE;
|
||||
}
|
||||
- maybe_start_pending_initial_login (manager, display);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
char *id;
|
||||
|
||||
gdm_display_get_id (display, &id, NULL);
|
||||
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
||||
g_free (id);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
|
||||
|
||||
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_start_user_session_operation (StartUserSessionOperation *operation)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (operation->session),
|
||||
"start-user-session-operation",
|
||||
NULL);
|
||||
g_object_unref (operation->session);
|
||||
@@ -1723,97 +1669,87 @@ on_start_user_session (StartUserSessionOperation *operation)
|
||||
gdm_session_reset (operation->session);
|
||||
destroy_start_user_session_operation (operation);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display = get_display_for_user_session (operation->session);
|
||||
|
||||
g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
|
||||
|
||||
session_id = gdm_session_get_conversation_session_id (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
|
||||
/* In this case, the greeter's display is morphing into
|
||||
* the user session display. Kill the greeter on this session
|
||||
* and let the user session follow the same display. */
|
||||
gdm_display_stop_greeter_session (display);
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
|
||||
g_object_ref (display);
|
||||
if (doing_initial_setup) {
|
||||
g_debug ("GdmManager: closing down initial setup display");
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
-
|
||||
- /* We can't start the user session until the finished display
|
||||
- * starts to respawn (since starting an X server and bringing
|
||||
- * one down at the same time is a no go)
|
||||
- */
|
||||
- g_assert (self->priv->initial_login_operation == NULL);
|
||||
- self->priv->initial_login_operation = operation;
|
||||
- starting_user_session_right_away = FALSE;
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
!gdm_session_client_is_connected (operation->session)) {
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
}
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
session_id);
|
||||
}
|
||||
|
||||
- if (starting_user_session_right_away) {
|
||||
- start_user_session (operation->manager, operation);
|
||||
- }
|
||||
+ start_user_session (operation->manager, operation);
|
||||
|
||||
out:
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_start_user_session (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
StartUserSessionOperation *operation;
|
||||
|
||||
operation = g_slice_new0 (StartUserSessionOperation);
|
||||
operation->manager = manager;
|
||||
operation->session = g_object_ref (session);
|
||||
operation->service_name = g_strdup (service_name);
|
||||
|
||||
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
|
||||
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
|
||||
}
|
||||
|
||||
static void
|
||||
start_user_session_if_ready (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
gboolean start_when_ready;
|
||||
|
||||
start_when_ready = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "start-when-ready"));
|
||||
if (start_when_ready) {
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,309 @@
|
||||
From 3073c23c673ede5093c1f93fb0775c2cd3203d7f Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 30 Aug 2018 16:09:02 -0400
|
||||
Subject: [PATCH 28/51] gdm-wayland-session,gdm-x-session: register after delay
|
||||
|
||||
Right now gdm-x-session registers with GDM as soon as the
|
||||
X server is started, and gdm-wayland-session registers as
|
||||
soon as the session is started.
|
||||
|
||||
Ideally registration wouldn't happen until the session
|
||||
says things started successfully.
|
||||
|
||||
This commit inches us toward that ideal but adding a little
|
||||
timeout before proceeding with registration.
|
||||
|
||||
A future commit will add a new xsession file key to allow
|
||||
us to know whether or not the session manager of the session
|
||||
supports doing registration.
|
||||
---
|
||||
daemon/gdm-wayland-session.c | 23 ++++++++++++++++-------
|
||||
daemon/gdm-x-session.c | 25 +++++++++++++++++--------
|
||||
2 files changed, 33 insertions(+), 15 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
|
||||
index 94f49e19c..de1991b34 100644
|
||||
--- a/daemon/gdm-wayland-session.c
|
||||
+++ b/daemon/gdm-wayland-session.c
|
||||
@@ -427,60 +427,75 @@ init_state (State **state)
|
||||
static State state_allocation;
|
||||
|
||||
*state = &state_allocation;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_state (State **out_state)
|
||||
{
|
||||
State *state = *out_state;
|
||||
|
||||
g_clear_object (&state->cancellable);
|
||||
g_clear_object (&state->bus_connection);
|
||||
g_clear_object (&state->session_subprocess);
|
||||
g_clear_pointer (&state->environment, g_strfreev);
|
||||
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
||||
*out_state = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_sigterm (State *state)
|
||||
{
|
||||
g_cancellable_cancel (state->cancellable);
|
||||
|
||||
if (g_main_loop_is_running (state->main_loop)) {
|
||||
g_main_loop_quit (state->main_loop);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+on_registration_delay_complete (State *state)
|
||||
+{
|
||||
+ gboolean ret;
|
||||
+
|
||||
+ ret = register_display (state, state->cancellable);
|
||||
+
|
||||
+ if (!ret) {
|
||||
+ g_printerr ("Unable to register display with display manager\n");
|
||||
+ g_main_loop_quit (state->main_loop);
|
||||
+ }
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
State *state = NULL;
|
||||
GOptionContext *context = NULL;
|
||||
static char **args = NULL;
|
||||
gboolean debug = FALSE;
|
||||
gboolean ret;
|
||||
int exit_status = EX_OK;
|
||||
static GOptionEntry entries [] = {
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
gdm_log_init ();
|
||||
|
||||
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
|
||||
g_option_context_parse (context, &argc, &argv, NULL);
|
||||
g_option_context_free (context);
|
||||
|
||||
if (args == NULL || args[0] == NULL || args[1] != NULL) {
|
||||
g_warning ("gdm-wayland-session takes one argument (the session)");
|
||||
exit_status = EX_USAGE;
|
||||
@@ -501,55 +516,49 @@ main (int argc,
|
||||
}
|
||||
|
||||
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
|
||||
state->debug_enabled = debug;
|
||||
|
||||
gdm_log_set_debug (debug);
|
||||
|
||||
state->main_loop = g_main_loop_new (NULL, FALSE);
|
||||
state->cancellable = g_cancellable_new ();
|
||||
|
||||
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
||||
|
||||
ret = spawn_bus (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session message bus\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
import_environment (state, state->cancellable);
|
||||
|
||||
ret = spawn_session (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
- ret = register_display (state, state->cancellable);
|
||||
-
|
||||
- if (!ret) {
|
||||
- g_printerr ("Unable to register display with display manager\n");
|
||||
- exit_status = EX_SOFTWARE;
|
||||
- goto out;
|
||||
- }
|
||||
+ g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
|
||||
|
||||
g_main_loop_run (state->main_loop);
|
||||
|
||||
/* Only use exit status of session if we're here because it exit */
|
||||
|
||||
if (state->session_subprocess == NULL) {
|
||||
exit_status = state->session_exit_status;
|
||||
}
|
||||
|
||||
out:
|
||||
if (state != NULL) {
|
||||
signal_subprocesses (state);
|
||||
wait_on_subprocesses (state);
|
||||
clear_state (&state);
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
|
||||
index 3b2fcef47..412999cf5 100644
|
||||
--- a/daemon/gdm-x-session.c
|
||||
+++ b/daemon/gdm-x-session.c
|
||||
@@ -783,60 +783,75 @@ init_state (State **state)
|
||||
}
|
||||
|
||||
static void
|
||||
clear_state (State **out_state)
|
||||
{
|
||||
State *state = *out_state;
|
||||
|
||||
g_clear_object (&state->cancellable);
|
||||
g_clear_object (&state->bus_connection);
|
||||
g_clear_object (&state->session_subprocess);
|
||||
g_clear_object (&state->x_subprocess);
|
||||
g_clear_pointer (&state->environment, g_strfreev);
|
||||
g_clear_pointer (&state->auth_file, g_free);
|
||||
g_clear_pointer (&state->display_name, g_free);
|
||||
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
||||
*out_state = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_sigterm (State *state)
|
||||
{
|
||||
g_cancellable_cancel (state->cancellable);
|
||||
|
||||
if (g_main_loop_is_running (state->main_loop)) {
|
||||
g_main_loop_quit (state->main_loop);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+on_registration_delay_complete (State *state)
|
||||
+{
|
||||
+ gboolean ret;
|
||||
+
|
||||
+ ret = register_display (state, state->cancellable);
|
||||
+
|
||||
+ if (!ret) {
|
||||
+ g_printerr ("Unable to register display with display manager\n");
|
||||
+ g_main_loop_quit (state->main_loop);
|
||||
+ }
|
||||
+
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
State *state = NULL;
|
||||
GOptionContext *context = NULL;
|
||||
static char **args = NULL;
|
||||
static gboolean run_script = FALSE;
|
||||
static gboolean allow_remote_connections = FALSE;
|
||||
gboolean debug = FALSE;
|
||||
gboolean ret;
|
||||
int exit_status = EX_OK;
|
||||
static GOptionEntry entries [] = {
|
||||
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
|
||||
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
gdm_log_init ();
|
||||
|
||||
context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
|
||||
g_option_context_parse (context, &argc, &argv, NULL);
|
||||
g_option_context_free (context);
|
||||
@@ -869,63 +884,57 @@ main (int argc,
|
||||
state->cancellable = g_cancellable_new ();
|
||||
|
||||
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
||||
|
||||
ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run X server\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spawn_bus (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session message bus\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
import_environment (state, state->cancellable);
|
||||
|
||||
ret = update_bus_environment (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to update bus environment\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
- ret = register_display (state, state->cancellable);
|
||||
-
|
||||
- if (!ret) {
|
||||
- g_printerr ("Unable to register display with display manager\n");
|
||||
- exit_status = EX_SOFTWARE;
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
ret = spawn_session (state, run_script, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
|
||||
+
|
||||
g_main_loop_run (state->main_loop);
|
||||
|
||||
/* Only use exit status of session if we're here because it exit */
|
||||
|
||||
if (state->session_subprocess == NULL) {
|
||||
exit_status = state->session_exit_status;
|
||||
}
|
||||
|
||||
out:
|
||||
if (state != NULL) {
|
||||
signal_subprocesses (state);
|
||||
wait_on_subprocesses (state);
|
||||
clear_state (&state);
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,399 @@
|
||||
From d85448e2e523deb1487e7e405a480e1c4e6a5f6f Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 31 Aug 2018 15:33:00 -0400
|
||||
Subject: [PATCH 29/51] local-display-factory: defer killing greeter until new
|
||||
session registers
|
||||
|
||||
At the moment we kill the greeter the second the VT change to the new
|
||||
session happens.
|
||||
|
||||
That can cause flicker if the new session doesn't take over the display
|
||||
quickly enough.
|
||||
|
||||
This commit defers killing the greeter until the new display registers.
|
||||
|
||||
Closes https://gitlab.gnome.org/GNOME/gdm/issues/413
|
||||
---
|
||||
daemon/gdm-display.h | 1 +
|
||||
daemon/gdm-local-display-factory.c | 43 +++++++++++++++++++++++++-----
|
||||
2 files changed, 38 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
|
||||
index 6d5e88df9..33dc3be41 100644
|
||||
--- a/daemon/gdm-display.h
|
||||
+++ b/daemon/gdm-display.h
|
||||
@@ -13,60 +13,61 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __GDM_DISPLAY_H
|
||||
#define __GDM_DISPLAY_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDM_TYPE_DISPLAY (gdm_display_get_type ())
|
||||
#define GDM_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_DISPLAY, GdmDisplay))
|
||||
#define GDM_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_DISPLAY, GdmDisplayClass))
|
||||
#define GDM_IS_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_DISPLAY))
|
||||
#define GDM_IS_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_DISPLAY))
|
||||
#define GDM_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_DISPLAY, GdmDisplayClass))
|
||||
|
||||
typedef struct GdmDisplayPrivate GdmDisplayPrivate;
|
||||
|
||||
typedef enum {
|
||||
GDM_DISPLAY_UNMANAGED = 0,
|
||||
GDM_DISPLAY_PREPARED,
|
||||
GDM_DISPLAY_MANAGED,
|
||||
+ GDM_DISPLAY_WAITING_TO_FINISH,
|
||||
GDM_DISPLAY_FINISHED,
|
||||
GDM_DISPLAY_FAILED,
|
||||
} GdmDisplayStatus;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObject parent;
|
||||
GdmDisplayPrivate *priv;
|
||||
} GdmDisplay;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
/* methods */
|
||||
gboolean (*prepare) (GdmDisplay *display);
|
||||
void (*manage) (GdmDisplay *self);
|
||||
} GdmDisplayClass;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDM_DISPLAY_ERROR_GENERAL,
|
||||
GDM_DISPLAY_ERROR_GETTING_USER_INFO,
|
||||
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
|
||||
} GdmDisplayError;
|
||||
|
||||
#define GDM_DISPLAY_ERROR gdm_display_error_quark ()
|
||||
|
||||
GQuark gdm_display_error_quark (void);
|
||||
GType gdm_display_get_type (void);
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 127127005..bc6ac6855 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -241,60 +241,90 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_object_set (display,
|
||||
"seat-id", "seat0",
|
||||
"allow-timed-login", FALSE,
|
||||
NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (! gdm_display_get_id (display, id, NULL)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
/* ref either held by store or not at all */
|
||||
g_object_unref (display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
|
||||
+ GdmDisplay *display,
|
||||
+ const char *seat_id)
|
||||
+{
|
||||
+ if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
|
||||
+ return FALSE;
|
||||
+
|
||||
+ g_debug ("GdmLocalDisplayFactory: finish background display\n");
|
||||
+ gdm_display_stop_greeter_session (display);
|
||||
+ gdm_display_unmanage (display);
|
||||
+ gdm_display_finish (display);
|
||||
+
|
||||
+ return FALSE;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+finish_waiting_displays_on_seat (GdmLocalDisplayFactory *factory,
|
||||
+ const char *seat_id)
|
||||
+{
|
||||
+ GdmDisplayStore *store;
|
||||
+
|
||||
+ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
+
|
||||
+ gdm_display_store_foreach (store,
|
||||
+ (GdmDisplayStoreFunc) finish_display_on_seat_if_waiting,
|
||||
+ (gpointer)
|
||||
+ seat_id);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
int status;
|
||||
int num;
|
||||
char *seat_id = NULL;
|
||||
char *session_type = NULL;
|
||||
char *session_class = NULL;
|
||||
gboolean is_initial = TRUE;
|
||||
gboolean is_local = TRUE;
|
||||
|
||||
num = -1;
|
||||
gdm_display_get_x11_display_number (display, &num, NULL);
|
||||
|
||||
g_object_get (display,
|
||||
"seat-id", &seat_id,
|
||||
"is-initial", &is_initial,
|
||||
"is-local", &is_local,
|
||||
"session-type", &session_type,
|
||||
"session-class", &session_class,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
/* remove the display number from factory->priv->used_display_numbers
|
||||
@@ -324,60 +354,63 @@ on_display_status_changed (GdmDisplay *display,
|
||||
/* Create a new equivalent display if it was static */
|
||||
if (is_local) {
|
||||
|
||||
factory->priv->num_failures++;
|
||||
|
||||
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
||||
/* oh shit */
|
||||
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
||||
} else {
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
if (g_strcmp0 (session_type, "wayland") == 0) {
|
||||
g_free (session_type);
|
||||
session_type = NULL;
|
||||
|
||||
/* workaround logind race for now
|
||||
* bug 1643874
|
||||
*/
|
||||
g_usleep (2 * G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
#endif
|
||||
create_display (factory, seat_id, session_type, is_initial);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
break;
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
break;
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
+ finish_waiting_displays_on_seat (factory, seat_id);
|
||||
+ break;
|
||||
+ case GDM_DISPLAY_WAITING_TO_FINISH:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
g_free (session_type);
|
||||
g_free (session_class);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_by_seat_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
char *current;
|
||||
gboolean res;
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
||||
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -561,84 +594,82 @@ on_seat_new (GDBusConnection *connection,
|
||||
|
||||
static void
|
||||
on_seat_removed (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *seat;
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
static gboolean
|
||||
lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
const char *current;
|
||||
|
||||
current = gdm_display_get_session_id (display);
|
||||
return g_strcmp0 (current, looking_for) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
-maybe_stop_greeter_display (GdmDisplay *display)
|
||||
+maybe_stop_greeter_in_background (GdmDisplay *display)
|
||||
{
|
||||
g_autofree char *display_session_type = NULL;
|
||||
|
||||
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"session-type", &display_session_type,
|
||||
NULL);
|
||||
|
||||
/* we can only stop greeter for wayland sessions, since
|
||||
* X server would jump back on exit */
|
||||
if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
- g_debug ("GdmLocalDisplayFactory: killing login window since its now unused");
|
||||
- gdm_display_stop_greeter_session (display);
|
||||
- gdm_display_unmanage (display);
|
||||
- gdm_display_finish (display);
|
||||
+ g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
||||
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_vt_changed (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GIOStatus status;
|
||||
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
||||
g_autofree char *tty_of_previous_vt = NULL;
|
||||
g_autofree char *tty_of_active_vt = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
g_autofree char *active_session_id = NULL;
|
||||
const char *session_type = NULL;
|
||||
int ret;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
||||
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
||||
|
||||
if (condition & G_IO_PRI) {
|
||||
g_autoptr (GError) error = NULL;
|
||||
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
||||
|
||||
if (error != NULL) {
|
||||
g_warning ("could not read active VT from kernel: %s", error->message);
|
||||
}
|
||||
switch (status) {
|
||||
case G_IO_STATUS_ERROR:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_EOF:
|
||||
@@ -678,61 +709,61 @@ on_vt_changed (GIOChannel *source,
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
||||
tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
||||
|
||||
/* if the old VT was running a wayland login screen kill it
|
||||
*/
|
||||
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
||||
unsigned int vt;
|
||||
|
||||
ret = sd_session_get_vt (login_session_id, &vt);
|
||||
if (ret == 0 && vt != 0) {
|
||||
g_autofree char *tty_of_login_window_vt = NULL;
|
||||
|
||||
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
||||
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
|
||||
if (display != NULL)
|
||||
- maybe_stop_greeter_display (display);
|
||||
+ maybe_stop_greeter_in_background (display);
|
||||
} else {
|
||||
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if user jumped back to initial vt and it's empty put a login screen
|
||||
* on it (unless a login screen is already running elsewhere, then
|
||||
* jump to that login screen)
|
||||
*/
|
||||
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
g_autofree char *state = NULL;
|
||||
ret = sd_session_get_state (active_session_id, &state);
|
||||
|
||||
/* if there's something already running on the active VT then bail */
|
||||
if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
session_type = "wayland";
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,708 @@
|
||||
From 0ff911467265831006aac6216060dbecff84c1cb Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 4 Sep 2018 10:56:45 +0200
|
||||
Subject: [PATCH 30/51] daemon: Move the waiting the session to have taken over
|
||||
the fb to gdm-local-display-factory
|
||||
|
||||
Commit 708618746683 ("gdm-wayland-session,gdm-x-session: register after
|
||||
delay") delayed displays changing their status from PREPARED to MANAGED
|
||||
so that their status would not change until the session has had a change
|
||||
to install its own framebuffer and tell the GPU to scanout this new fb.
|
||||
|
||||
Commit 74ee77717df7 ("local-display-factory: defer killing greeter until
|
||||
new session registers") uses this to avoid a flicker when transitioning
|
||||
from the greeter to the user-session by deferring the stopping of the
|
||||
greeter-session until the new display moves to the MANAGED state.
|
||||
|
||||
But this only works when transitioning to a new user-session, when moving
|
||||
to an existing user-session (fast user switching) the display already
|
||||
is in MANAGED state and instead of deferring the stopping of the greeter
|
||||
commit 74ee77717df7 causes us to now never stop the greeter-session.
|
||||
|
||||
This commit fixes this by starting a timeout when switching away from
|
||||
the initial-vt and letting that timeout stop the greeter-session.
|
||||
|
||||
This commit removes the finish_waiting_displays_on_seat() call when the
|
||||
display's status changes to MANAGED, so that we still only have one code
|
||||
path stopping the greeter and not two.
|
||||
|
||||
This means we also no longer need to delay registering the display. So this
|
||||
commit removes the code adding the delay (reverts commit 74ee77717df7).
|
||||
|
||||
Note this commit uses a delay of 10 seconds, rather then 2 seconds. The
|
||||
transition to a new user-session takes about 8 seconds on my budget
|
||||
Apollo Lake based laptop (with SSD).
|
||||
|
||||
Note this all really is a workaround, the proper solution for this would
|
||||
be able to tell the kernel to keep the greeter framebuffer around until
|
||||
a new framebuffer is installed. There is a patch to add a new unref_fb
|
||||
ioctl for this: https://www.spinics.net/lists/dri-devel/msg140912.html .
|
||||
We need to get this patch upstream and teach mutter to use it.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 29 ++++++++++++++++++++++++++---
|
||||
daemon/gdm-wayland-session.c | 23 +++++++----------------
|
||||
daemon/gdm-x-session.c | 25 ++++++++-----------------
|
||||
3 files changed, 41 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index bc6ac6855..be6b377be 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -22,76 +22,78 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-object.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
#include "gdm-common.h"
|
||||
#include "gdm-manager.h"
|
||||
#include "gdm-display-factory.h"
|
||||
#include "gdm-local-display-factory.h"
|
||||
#include "gdm-local-display-factory-glue.h"
|
||||
|
||||
#include "gdm-settings-keys.h"
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-display-store.h"
|
||||
#include "gdm-local-display.h"
|
||||
#include "gdm-legacy-display.h"
|
||||
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
||||
|
||||
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
||||
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
||||
|
||||
#define MAX_DISPLAY_FAILURES 5
|
||||
+#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
|
||||
|
||||
struct GdmLocalDisplayFactoryPrivate
|
||||
{
|
||||
GdmDBusLocalDisplayFactory *skeleton;
|
||||
GDBusConnection *connection;
|
||||
GHashTable *used_display_numbers;
|
||||
|
||||
/* FIXME: this needs to be per seat? */
|
||||
guint num_failures;
|
||||
|
||||
guint seat_new_id;
|
||||
guint seat_removed_id;
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
char *tty_of_active_vt;
|
||||
guint active_vt_watch_id;
|
||||
+ guint wait_to_finish_timeout_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
};
|
||||
|
||||
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
|
||||
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
|
||||
static void gdm_local_display_factory_finalize (GObject *object);
|
||||
|
||||
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial_display);
|
||||
|
||||
static void on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory);
|
||||
|
||||
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
|
||||
static gpointer local_display_factory_object = NULL;
|
||||
static gboolean lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data);
|
||||
|
||||
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
||||
|
||||
GQuark
|
||||
gdm_local_display_factory_error_quark (void)
|
||||
@@ -354,61 +356,60 @@ on_display_status_changed (GdmDisplay *display,
|
||||
/* Create a new equivalent display if it was static */
|
||||
if (is_local) {
|
||||
|
||||
factory->priv->num_failures++;
|
||||
|
||||
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
||||
/* oh shit */
|
||||
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
||||
} else {
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
if (g_strcmp0 (session_type, "wayland") == 0) {
|
||||
g_free (session_type);
|
||||
session_type = NULL;
|
||||
|
||||
/* workaround logind race for now
|
||||
* bug 1643874
|
||||
*/
|
||||
g_usleep (2 * G_USEC_PER_SEC);
|
||||
}
|
||||
|
||||
#endif
|
||||
create_display (factory, seat_id, session_type, is_initial);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
break;
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
break;
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
- finish_waiting_displays_on_seat (factory, seat_id);
|
||||
break;
|
||||
case GDM_DISPLAY_WAITING_TO_FINISH:
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
g_free (session_type);
|
||||
g_free (session_class);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_by_seat_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
char *current;
|
||||
gboolean res;
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
||||
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -593,83 +594,101 @@ on_seat_new (GDBusConnection *connection,
|
||||
}
|
||||
|
||||
static void
|
||||
on_seat_removed (GDBusConnection *connection,
|
||||
const gchar *sender_name,
|
||||
const gchar *object_path,
|
||||
const gchar *interface_name,
|
||||
const gchar *signal_name,
|
||||
GVariant *parameters,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *seat;
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
static gboolean
|
||||
lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
const char *current;
|
||||
|
||||
current = gdm_display_get_session_id (display);
|
||||
return g_strcmp0 (current, looking_for) == 0;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
|
||||
+{
|
||||
+ finish_waiting_displays_on_seat (factory, "seat0");
|
||||
+ factory->priv->wait_to_finish_timeout_id = 0;
|
||||
+ return G_SOURCE_REMOVE;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
-maybe_stop_greeter_in_background (GdmDisplay *display)
|
||||
+maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
|
||||
+ GdmDisplay *display)
|
||||
{
|
||||
g_autofree char *display_session_type = NULL;
|
||||
|
||||
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"session-type", &display_session_type,
|
||||
NULL);
|
||||
|
||||
/* we can only stop greeter for wayland sessions, since
|
||||
* X server would jump back on exit */
|
||||
if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
||||
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
+
|
||||
+ /* We stop the greeter after a timeout to avoid flicker */
|
||||
+ if (factory->priv->wait_to_finish_timeout_id != 0)
|
||||
+ g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
||||
+
|
||||
+ factory->priv->wait_to_finish_timeout_id =
|
||||
+ g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
|
||||
+ (GSourceFunc)wait_to_finish_timeout,
|
||||
+ factory);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_vt_changed (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GIOStatus status;
|
||||
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
||||
g_autofree char *tty_of_previous_vt = NULL;
|
||||
g_autofree char *tty_of_active_vt = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
g_autofree char *active_session_id = NULL;
|
||||
const char *session_type = NULL;
|
||||
int ret;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
||||
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
||||
|
||||
if (condition & G_IO_PRI) {
|
||||
g_autoptr (GError) error = NULL;
|
||||
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
||||
|
||||
if (error != NULL) {
|
||||
g_warning ("could not read active VT from kernel: %s", error->message);
|
||||
}
|
||||
switch (status) {
|
||||
case G_IO_STATUS_ERROR:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_EOF:
|
||||
@@ -709,61 +728,61 @@ on_vt_changed (GIOChannel *source,
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
||||
tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
||||
|
||||
/* if the old VT was running a wayland login screen kill it
|
||||
*/
|
||||
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
||||
unsigned int vt;
|
||||
|
||||
ret = sd_session_get_vt (login_session_id, &vt);
|
||||
if (ret == 0 && vt != 0) {
|
||||
g_autofree char *tty_of_login_window_vt = NULL;
|
||||
|
||||
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
||||
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
|
||||
if (display != NULL)
|
||||
- maybe_stop_greeter_in_background (display);
|
||||
+ maybe_stop_greeter_in_background (factory, display);
|
||||
} else {
|
||||
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if user jumped back to initial vt and it's empty put a login screen
|
||||
* on it (unless a login screen is already running elsewhere, then
|
||||
* jump to that login screen)
|
||||
*/
|
||||
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
||||
|
||||
if (ret == 0) {
|
||||
g_autofree char *state = NULL;
|
||||
ret = sd_session_get_state (active_session_id, &state);
|
||||
|
||||
/* if there's something already running on the active VT then bail */
|
||||
if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
session_type = "wayland";
|
||||
@@ -803,60 +822,64 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
||||
g_object_unref);
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
|
||||
|
||||
if (io_channel != NULL) {
|
||||
factory->priv->active_vt_watch_id =
|
||||
g_io_add_watch (io_channel,
|
||||
G_IO_PRI,
|
||||
(GIOFunc)
|
||||
on_vt_changed,
|
||||
factory);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
if (factory->priv->seat_new_id) {
|
||||
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
||||
factory->priv->seat_new_id);
|
||||
factory->priv->seat_new_id = 0;
|
||||
}
|
||||
if (factory->priv->seat_removed_id) {
|
||||
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
||||
factory->priv->seat_removed_id);
|
||||
factory->priv->seat_removed_id = 0;
|
||||
}
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ if (factory->priv->wait_to_finish_timeout_id != 0) {
|
||||
+ g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
||||
+ factory->priv->wait_to_finish_timeout_id = 0;
|
||||
+ }
|
||||
if (factory->priv->active_vt_watch_id) {
|
||||
g_source_remove (factory->priv->active_vt_watch_id);
|
||||
factory->priv->active_vt_watch_id = 0;
|
||||
}
|
||||
|
||||
g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_added (GdmDisplayStore *display_store,
|
||||
const char *id,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_lookup (display_store, id);
|
||||
|
||||
if (display != NULL) {
|
||||
g_signal_connect_object (display, "notify::status",
|
||||
G_CALLBACK (on_display_status_changed),
|
||||
factory,
|
||||
0);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
|
||||
index de1991b34..94f49e19c 100644
|
||||
--- a/daemon/gdm-wayland-session.c
|
||||
+++ b/daemon/gdm-wayland-session.c
|
||||
@@ -427,75 +427,60 @@ init_state (State **state)
|
||||
static State state_allocation;
|
||||
|
||||
*state = &state_allocation;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_state (State **out_state)
|
||||
{
|
||||
State *state = *out_state;
|
||||
|
||||
g_clear_object (&state->cancellable);
|
||||
g_clear_object (&state->bus_connection);
|
||||
g_clear_object (&state->session_subprocess);
|
||||
g_clear_pointer (&state->environment, g_strfreev);
|
||||
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
||||
*out_state = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_sigterm (State *state)
|
||||
{
|
||||
g_cancellable_cancel (state->cancellable);
|
||||
|
||||
if (g_main_loop_is_running (state->main_loop)) {
|
||||
g_main_loop_quit (state->main_loop);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
-on_registration_delay_complete (State *state)
|
||||
-{
|
||||
- gboolean ret;
|
||||
-
|
||||
- ret = register_display (state, state->cancellable);
|
||||
-
|
||||
- if (!ret) {
|
||||
- g_printerr ("Unable to register display with display manager\n");
|
||||
- g_main_loop_quit (state->main_loop);
|
||||
- }
|
||||
-
|
||||
- return G_SOURCE_REMOVE;
|
||||
-}
|
||||
-
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
State *state = NULL;
|
||||
GOptionContext *context = NULL;
|
||||
static char **args = NULL;
|
||||
gboolean debug = FALSE;
|
||||
gboolean ret;
|
||||
int exit_status = EX_OK;
|
||||
static GOptionEntry entries [] = {
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
gdm_log_init ();
|
||||
|
||||
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
|
||||
g_option_context_parse (context, &argc, &argv, NULL);
|
||||
g_option_context_free (context);
|
||||
|
||||
if (args == NULL || args[0] == NULL || args[1] != NULL) {
|
||||
g_warning ("gdm-wayland-session takes one argument (the session)");
|
||||
exit_status = EX_USAGE;
|
||||
@@ -516,49 +501,55 @@ main (int argc,
|
||||
}
|
||||
|
||||
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
|
||||
state->debug_enabled = debug;
|
||||
|
||||
gdm_log_set_debug (debug);
|
||||
|
||||
state->main_loop = g_main_loop_new (NULL, FALSE);
|
||||
state->cancellable = g_cancellable_new ();
|
||||
|
||||
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
||||
|
||||
ret = spawn_bus (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session message bus\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
import_environment (state, state->cancellable);
|
||||
|
||||
ret = spawn_session (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
- g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
|
||||
+ ret = register_display (state, state->cancellable);
|
||||
+
|
||||
+ if (!ret) {
|
||||
+ g_printerr ("Unable to register display with display manager\n");
|
||||
+ exit_status = EX_SOFTWARE;
|
||||
+ goto out;
|
||||
+ }
|
||||
|
||||
g_main_loop_run (state->main_loop);
|
||||
|
||||
/* Only use exit status of session if we're here because it exit */
|
||||
|
||||
if (state->session_subprocess == NULL) {
|
||||
exit_status = state->session_exit_status;
|
||||
}
|
||||
|
||||
out:
|
||||
if (state != NULL) {
|
||||
signal_subprocesses (state);
|
||||
wait_on_subprocesses (state);
|
||||
clear_state (&state);
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
|
||||
index 412999cf5..3b2fcef47 100644
|
||||
--- a/daemon/gdm-x-session.c
|
||||
+++ b/daemon/gdm-x-session.c
|
||||
@@ -783,75 +783,60 @@ init_state (State **state)
|
||||
}
|
||||
|
||||
static void
|
||||
clear_state (State **out_state)
|
||||
{
|
||||
State *state = *out_state;
|
||||
|
||||
g_clear_object (&state->cancellable);
|
||||
g_clear_object (&state->bus_connection);
|
||||
g_clear_object (&state->session_subprocess);
|
||||
g_clear_object (&state->x_subprocess);
|
||||
g_clear_pointer (&state->environment, g_strfreev);
|
||||
g_clear_pointer (&state->auth_file, g_free);
|
||||
g_clear_pointer (&state->display_name, g_free);
|
||||
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
||||
*out_state = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_sigterm (State *state)
|
||||
{
|
||||
g_cancellable_cancel (state->cancellable);
|
||||
|
||||
if (g_main_loop_is_running (state->main_loop)) {
|
||||
g_main_loop_quit (state->main_loop);
|
||||
}
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
-on_registration_delay_complete (State *state)
|
||||
-{
|
||||
- gboolean ret;
|
||||
-
|
||||
- ret = register_display (state, state->cancellable);
|
||||
-
|
||||
- if (!ret) {
|
||||
- g_printerr ("Unable to register display with display manager\n");
|
||||
- g_main_loop_quit (state->main_loop);
|
||||
- }
|
||||
-
|
||||
- return G_SOURCE_REMOVE;
|
||||
-}
|
||||
-
|
||||
int
|
||||
main (int argc,
|
||||
char **argv)
|
||||
{
|
||||
State *state = NULL;
|
||||
GOptionContext *context = NULL;
|
||||
static char **args = NULL;
|
||||
static gboolean run_script = FALSE;
|
||||
static gboolean allow_remote_connections = FALSE;
|
||||
gboolean debug = FALSE;
|
||||
gboolean ret;
|
||||
int exit_status = EX_OK;
|
||||
static GOptionEntry entries [] = {
|
||||
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
|
||||
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
setlocale (LC_ALL, "");
|
||||
|
||||
gdm_log_init ();
|
||||
|
||||
context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
|
||||
g_option_context_add_main_entries (context, entries, NULL);
|
||||
|
||||
g_option_context_parse (context, &argc, &argv, NULL);
|
||||
g_option_context_free (context);
|
||||
@@ -884,57 +869,63 @@ main (int argc,
|
||||
state->cancellable = g_cancellable_new ();
|
||||
|
||||
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
||||
|
||||
ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run X server\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = spawn_bus (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session message bus\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
import_environment (state, state->cancellable);
|
||||
|
||||
ret = update_bus_environment (state, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to update bus environment\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ ret = register_display (state, state->cancellable);
|
||||
+
|
||||
+ if (!ret) {
|
||||
+ g_printerr ("Unable to register display with display manager\n");
|
||||
+ exit_status = EX_SOFTWARE;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
ret = spawn_session (state, run_script, state->cancellable);
|
||||
|
||||
if (!ret) {
|
||||
g_printerr ("Unable to run session\n");
|
||||
exit_status = EX_SOFTWARE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
- g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
|
||||
-
|
||||
g_main_loop_run (state->main_loop);
|
||||
|
||||
/* Only use exit status of session if we're here because it exit */
|
||||
|
||||
if (state->session_subprocess == NULL) {
|
||||
exit_status = state->session_exit_status;
|
||||
}
|
||||
|
||||
out:
|
||||
if (state != NULL) {
|
||||
signal_subprocesses (state);
|
||||
wait_on_subprocesses (state);
|
||||
clear_state (&state);
|
||||
}
|
||||
|
||||
return exit_status;
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,100 @@
|
||||
From 59b3b809400dfac25410cf99dbc15cb5f66f85a3 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 25 Sep 2018 14:52:15 -0400
|
||||
Subject: [PATCH 31/51] local-display-factory: don't autoreap initial-setup
|
||||
|
||||
We automatically kill the login screen when switching VTs away
|
||||
from it, but we should never kill the initial-setup screen in
|
||||
that situation.
|
||||
|
||||
This commit adds a check to prevent that from happening.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index be6b377be..13d56dcff 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -607,70 +607,78 @@ on_seat_removed (GDBusConnection *connection,
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
static gboolean
|
||||
lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
const char *current;
|
||||
|
||||
current = gdm_display_get_session_id (display);
|
||||
return g_strcmp0 (current, looking_for) == 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
finish_waiting_displays_on_seat (factory, "seat0");
|
||||
factory->priv->wait_to_finish_timeout_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
g_autofree char *display_session_type = NULL;
|
||||
+ gboolean doing_initial_setup = FALSE;
|
||||
|
||||
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"session-type", &display_session_type,
|
||||
+ "doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
+ /* we don't ever stop initial-setup implicitly */
|
||||
+ if (doing_initial_setup) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
/* we can only stop greeter for wayland sessions, since
|
||||
* X server would jump back on exit */
|
||||
if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
||||
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
|
||||
/* We stop the greeter after a timeout to avoid flicker */
|
||||
if (factory->priv->wait_to_finish_timeout_id != 0)
|
||||
g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
||||
|
||||
factory->priv->wait_to_finish_timeout_id =
|
||||
g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
|
||||
(GSourceFunc)wait_to_finish_timeout,
|
||||
factory);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_vt_changed (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GIOStatus status;
|
||||
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
||||
g_autofree char *tty_of_previous_vt = NULL;
|
||||
g_autofree char *tty_of_active_vt = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
--
|
||||
2.27.0
|
||||
|
460
SOURCES/0032-manager-rework-how-autologin-is-figured-out.patch
Normal file
460
SOURCES/0032-manager-rework-how-autologin-is-figured-out.patch
Normal file
@ -0,0 +1,460 @@
|
||||
From 566720ce07db8745c0ae6780ff289292dc0a9b60 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 25 Sep 2018 10:59:37 -0400
|
||||
Subject: [PATCH 32/51] manager: rework how autologin is figured out
|
||||
|
||||
At the moment we decide whether or not to perform autologin, by
|
||||
looking at if the display is the initial VT display and if autologin
|
||||
hasn't been started before.
|
||||
|
||||
That isn't going to work in the future when autologin is started
|
||||
on a non-initial vt.
|
||||
|
||||
This commit changes GDM to instead check if the seat is seat0, and
|
||||
if autologin hasn't run before, before deciding to do autologin.
|
||||
---
|
||||
daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++------------
|
||||
1 file changed, 34 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index fb7b1ec4b..228cec6ff 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -51,75 +51,76 @@
|
||||
#include "gdm-session.h"
|
||||
#include "gdm-session-record.h"
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-settings-keys.h"
|
||||
#include "gdm-xdmcp-display-factory.h"
|
||||
#include "gdm-xdmcp-chooser-display.h"
|
||||
|
||||
#define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
|
||||
|
||||
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
||||
#define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager"
|
||||
#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
|
||||
|
||||
#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdmManager *manager;
|
||||
GdmSession *session;
|
||||
char *service_name;
|
||||
guint idle_id;
|
||||
} StartUserSessionOperation;
|
||||
|
||||
struct GdmManagerPrivate
|
||||
{
|
||||
GdmDisplayStore *display_store;
|
||||
GdmLocalDisplayFactory *local_factory;
|
||||
#ifdef HAVE_LIBXDMCP
|
||||
GdmXdmcpDisplayFactory *xdmcp_factory;
|
||||
#endif
|
||||
+ GdmDisplay *automatic_login_display;
|
||||
GList *user_sessions;
|
||||
GHashTable *transient_sessions;
|
||||
GHashTable *open_reauthentication_requests;
|
||||
gboolean xdmcp_enabled;
|
||||
|
||||
gboolean started;
|
||||
gboolean show_local_greeter;
|
||||
|
||||
GDBusConnection *connection;
|
||||
GDBusObjectManagerServer *object_manager;
|
||||
|
||||
#ifdef WITH_PLYMOUTH
|
||||
guint plymouth_is_running : 1;
|
||||
#endif
|
||||
- guint ran_once : 1;
|
||||
+ guint did_automatic_login : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_XDMCP_ENABLED,
|
||||
PROP_SHOW_LOCAL_GREETER
|
||||
};
|
||||
|
||||
enum {
|
||||
DISPLAY_ADDED,
|
||||
DISPLAY_REMOVED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
SESSION_RECORD_LOGIN,
|
||||
SESSION_RECORD_LOGOUT,
|
||||
SESSION_RECORD_FAILED,
|
||||
} SessionRecord;
|
||||
|
||||
static guint signals [LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void gdm_manager_class_init (GdmManagerClass *klass);
|
||||
static void gdm_manager_init (GdmManager *manager);
|
||||
static void gdm_manager_dispose (GObject *object);
|
||||
|
||||
static GdmSession *create_user_session_for_display (GdmManager *manager,
|
||||
GdmDisplay *display,
|
||||
uid_t allowed_user);
|
||||
static void start_user_session (GdmManager *manager,
|
||||
@@ -1415,67 +1416,74 @@ typedef struct {
|
||||
static void
|
||||
destroy_username_lookup_operation (UsernameLookupOperation *operation)
|
||||
{
|
||||
g_object_unref (operation->manager);
|
||||
g_object_unref (operation->display);
|
||||
g_free (operation->username);
|
||||
g_free (operation);
|
||||
}
|
||||
|
||||
static void
|
||||
on_user_is_loaded_changed (ActUser *user,
|
||||
GParamSpec *pspec,
|
||||
UsernameLookupOperation *operation)
|
||||
{
|
||||
if (act_user_is_loaded (user)) {
|
||||
set_up_automatic_login_session_if_user_exists (operation->manager, operation->display, user);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (user),
|
||||
G_CALLBACK (on_user_is_loaded_changed),
|
||||
operation);
|
||||
destroy_username_lookup_operation (operation);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
ActUserManager *user_manager;
|
||||
ActUser *user;
|
||||
gboolean loaded;
|
||||
- gboolean is_initial_display = FALSE;
|
||||
+ gboolean seat_can_autologin = FALSE, seat_did_autologin = FALSE;
|
||||
gboolean autologin_enabled = FALSE;
|
||||
+ g_autofree char *seat_id = NULL;
|
||||
char *username = NULL;
|
||||
|
||||
- g_object_get (G_OBJECT (display), "is-initial", &is_initial_display, NULL);
|
||||
+ g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
|
||||
+
|
||||
+ if (g_strcmp0 (seat_id, "seat0") == 0)
|
||||
+ seat_can_autologin = TRUE;
|
||||
+
|
||||
+ if (manager->priv->did_automatic_login || manager->priv->automatic_login_display != NULL)
|
||||
+ seat_did_autologin = TRUE;
|
||||
|
||||
- if (!manager->priv->ran_once && is_initial_display)
|
||||
+ if (seat_can_autologin && !seat_did_autologin)
|
||||
autologin_enabled = get_automatic_login_details (manager, &username);
|
||||
|
||||
if (!autologin_enabled) {
|
||||
g_free (username);
|
||||
|
||||
#ifdef HAVE_LIBXDMCP
|
||||
if (GDM_IS_XDMCP_CHOOSER_DISPLAY (display)) {
|
||||
set_up_chooser_session (manager, display);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
set_up_greeter_session (manager, display);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether the user really exists before committing to autologin. */
|
||||
user_manager = act_user_manager_get_default ();
|
||||
user = act_user_manager_get_user (user_manager, username);
|
||||
g_object_get (user_manager, "is-loaded", &loaded, NULL);
|
||||
|
||||
if (loaded) {
|
||||
set_up_automatic_login_session_if_user_exists (manager, display, user);
|
||||
} else {
|
||||
UsernameLookupOperation *operation;
|
||||
|
||||
operation = g_new (UsernameLookupOperation, 1);
|
||||
operation->manager = g_object_ref (manager);
|
||||
operation->display = g_object_ref (display);
|
||||
operation->username = username;
|
||||
@@ -1512,62 +1520,72 @@ on_display_status_changed (GdmDisplay *display,
|
||||
"session-type", &session_type,
|
||||
NULL);
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
switch (status) {
|
||||
case GDM_DISPLAY_PREPARED:
|
||||
case GDM_DISPLAY_MANAGED:
|
||||
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
|
||||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
|
||||
char *session_class;
|
||||
|
||||
g_object_get (display,
|
||||
"session-class", &session_class,
|
||||
NULL);
|
||||
if (g_strcmp0 (session_class, "greeter") == 0)
|
||||
set_up_session (manager, display);
|
||||
g_free (session_class);
|
||||
}
|
||||
break;
|
||||
case GDM_DISPLAY_FAILED:
|
||||
case GDM_DISPLAY_UNMANAGED:
|
||||
case GDM_DISPLAY_FINISHED:
|
||||
#ifdef WITH_PLYMOUTH
|
||||
if (quit_plymouth) {
|
||||
plymouth_quit_without_transition ();
|
||||
manager->priv->plymouth_is_running = FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
- if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
|
||||
- manager->priv->ran_once = TRUE;
|
||||
+ if (display == manager->priv->automatic_login_display) {
|
||||
+ g_clear_weak_pointer (&manager->priv->automatic_login_display);
|
||||
+
|
||||
+ manager->priv->did_automatic_login = TRUE;
|
||||
+
|
||||
+#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
+ if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) {
|
||||
+ /* we're going to fall back to X11, so try to autologin again
|
||||
+ */
|
||||
+ manager->priv->did_automatic_login = FALSE;
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
char *id;
|
||||
|
||||
gdm_display_get_id (display, &id, NULL);
|
||||
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
||||
g_free (id);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
|
||||
|
||||
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_start_user_session_operation (StartUserSessionOperation *operation)
|
||||
{
|
||||
g_object_set_data (G_OBJECT (operation->session),
|
||||
"start-user-session-operation",
|
||||
NULL);
|
||||
@@ -1621,132 +1639,134 @@ create_display_for_user_session (GdmManager *self,
|
||||
const char *session_id)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
/* at the moment we only create GdmLocalDisplay objects on seat0 */
|
||||
const char *seat_id = "seat0";
|
||||
|
||||
display = gdm_local_display_new ();
|
||||
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"seat-id", seat_id,
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
gdm_display_store_add (self->priv->display_store,
|
||||
display);
|
||||
g_object_set_data (G_OBJECT (session), "gdm-display", display);
|
||||
g_object_set_data_full (G_OBJECT (display),
|
||||
"gdm-user-session",
|
||||
g_object_ref (session),
|
||||
(GDestroyNotify)
|
||||
clean_user_session);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_start_user_session (StartUserSessionOperation *operation)
|
||||
{
|
||||
GdmManager *self = operation->manager;
|
||||
gboolean migrated;
|
||||
gboolean fail_if_already_switched = TRUE;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
- gboolean starting_user_session_right_away = TRUE;
|
||||
GdmDisplay *display;
|
||||
const char *session_id;
|
||||
|
||||
g_debug ("GdmManager: start or jump to session");
|
||||
|
||||
/* If there's already a session running, jump to it.
|
||||
* If the only session running is the one we just opened,
|
||||
* start a session on it.
|
||||
*/
|
||||
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
|
||||
|
||||
g_debug ("GdmManager: migrated: %d", migrated);
|
||||
if (migrated) {
|
||||
/* We don't stop the manager here because
|
||||
when Xorg exits it switches to the VT it was
|
||||
started from. That interferes with fast
|
||||
user switching. */
|
||||
gdm_session_reset (operation->session);
|
||||
destroy_start_user_session_operation (operation);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display = get_display_for_user_session (operation->session);
|
||||
|
||||
g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
|
||||
|
||||
session_id = gdm_session_get_conversation_session_id (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
|
||||
/* In this case, the greeter's display is morphing into
|
||||
* the user session display. Kill the greeter on this session
|
||||
* and let the user session follow the same display. */
|
||||
gdm_display_stop_greeter_session (display);
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
|
||||
g_object_ref (display);
|
||||
if (doing_initial_setup) {
|
||||
g_debug ("GdmManager: closing down initial setup display");
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
+ /* Give the user session a new display object for bookkeeping purposes */
|
||||
+ create_display_for_user_session (operation->manager,
|
||||
+ operation->session,
|
||||
+ session_id);
|
||||
+
|
||||
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
!gdm_session_client_is_connected (operation->session)) {
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
- }
|
||||
|
||||
- /* Give the user session a new display object for bookkeeping purposes */
|
||||
- create_display_for_user_session (operation->manager,
|
||||
- operation->session,
|
||||
- session_id);
|
||||
+ self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
|
||||
+ g_object_add_weak_pointer (G_OBJECT (display), (gpointer *) &self->priv->automatic_login_display);
|
||||
+ }
|
||||
}
|
||||
|
||||
start_user_session (operation->manager, operation);
|
||||
|
||||
out:
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_start_user_session (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
StartUserSessionOperation *operation;
|
||||
|
||||
operation = g_slice_new0 (StartUserSessionOperation);
|
||||
operation->manager = manager;
|
||||
operation->session = g_object_ref (session);
|
||||
operation->service_name = g_strdup (service_name);
|
||||
|
||||
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
|
||||
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
|
||||
}
|
||||
|
||||
static void
|
||||
start_user_session_if_ready (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
gboolean start_when_ready;
|
||||
@@ -2601,60 +2621,62 @@ unexport_display (const char *id,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
if (!g_dbus_connection_is_closed (manager->priv->connection))
|
||||
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
|
||||
}
|
||||
|
||||
static void
|
||||
finish_display (const char *id,
|
||||
GdmDisplay *display,
|
||||
GdmManager *manager)
|
||||
{
|
||||
gdm_display_stop_greeter_session (display);
|
||||
if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_manager_dispose (GObject *object)
|
||||
{
|
||||
GdmManager *manager;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (GDM_IS_MANAGER (object));
|
||||
|
||||
manager = GDM_MANAGER (object);
|
||||
|
||||
g_return_if_fail (manager->priv != NULL);
|
||||
|
||||
+ g_clear_weak_pointer (&manager->priv->automatic_login_display);
|
||||
+
|
||||
#ifdef HAVE_LIBXDMCP
|
||||
g_clear_object (&manager->priv->xdmcp_factory);
|
||||
#endif
|
||||
g_clear_object (&manager->priv->local_factory);
|
||||
g_clear_pointer (&manager->priv->open_reauthentication_requests,
|
||||
(GDestroyNotify)
|
||||
g_hash_table_unref);
|
||||
g_clear_pointer (&manager->priv->transient_sessions,
|
||||
(GDestroyNotify)
|
||||
g_hash_table_unref);
|
||||
|
||||
g_list_foreach (manager->priv->user_sessions,
|
||||
(GFunc) gdm_session_close,
|
||||
NULL);
|
||||
g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
|
||||
manager->priv->user_sessions = NULL;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
|
||||
G_CALLBACK (on_display_added),
|
||||
manager);
|
||||
g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
|
||||
G_CALLBACK (on_display_removed),
|
||||
manager);
|
||||
|
||||
if (!g_dbus_connection_is_closed (manager->priv->connection)) {
|
||||
gdm_display_store_foreach (manager->priv->display_store,
|
||||
(GdmDisplayStoreFunc)unexport_display,
|
||||
manager);
|
||||
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
|
||||
}
|
||||
--
|
||||
2.27.0
|
||||
|
85
SOURCES/0033-manager-correct-display-confusion.patch
Normal file
85
SOURCES/0033-manager-correct-display-confusion.patch
Normal file
@ -0,0 +1,85 @@
|
||||
From 05e49542a9de81731fce68614babe22d437e8fff Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Mon, 1 Oct 2018 11:05:57 -0400
|
||||
Subject: [PATCH 33/51] manager: correct display confusion
|
||||
|
||||
commit c5c5bf1f reworked autologin and broke it.
|
||||
|
||||
This commit addresses the breakage by accessing
|
||||
the proper display variable.
|
||||
|
||||
Closes https://gitlab.gnome.org/GNOME/gdm/issues/426
|
||||
---
|
||||
daemon/gdm-manager.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 228cec6ff..4c81dac7f 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1711,61 +1711,61 @@ on_start_user_session (StartUserSessionOperation *operation)
|
||||
if (doing_initial_setup) {
|
||||
g_debug ("GdmManager: closing down initial setup display");
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
session_id);
|
||||
|
||||
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
!gdm_session_client_is_connected (operation->session)) {
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
|
||||
self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
|
||||
- g_object_add_weak_pointer (G_OBJECT (display), (gpointer *) &self->priv->automatic_login_display);
|
||||
+ g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
|
||||
}
|
||||
}
|
||||
|
||||
start_user_session (operation->manager, operation);
|
||||
|
||||
out:
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_start_user_session (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
StartUserSessionOperation *operation;
|
||||
|
||||
operation = g_slice_new0 (StartUserSessionOperation);
|
||||
operation->manager = manager;
|
||||
operation->session = g_object_ref (session);
|
||||
operation->service_name = g_strdup (service_name);
|
||||
|
||||
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
|
||||
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
|
||||
}
|
||||
|
||||
static void
|
||||
start_user_session_if_ready (GdmManager *manager,
|
||||
GdmSession *session,
|
||||
const char *service_name)
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,99 @@
|
||||
From e4c9a998f89d429d31b02997f146c8218c0742bc Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Mon, 24 Sep 2018 14:45:38 -0400
|
||||
Subject: [PATCH 34/51] manager: don't run autologin display on tty1
|
||||
|
||||
tty1 is really meant for the login screen.
|
||||
If a user autologins on it and we need a login
|
||||
screen later, then the login screen has to go
|
||||
in some auxiliary VT which isn't very nice.
|
||||
|
||||
This commit changes autologin to not use the
|
||||
initial vt.
|
||||
---
|
||||
daemon/gdm-manager.c | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 4c81dac7f..e896c8945 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1308,74 +1308,72 @@ get_automatic_login_details (GdmManager *manager,
|
||||
} else {
|
||||
g_free (username);
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_username_for_greeter_display (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
if (doing_initial_setup) {
|
||||
return INITIAL_SETUP_USERNAME;
|
||||
} else {
|
||||
return GDM_USERNAME;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_automatic_login_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
GdmSession *session;
|
||||
char *display_session_type = NULL;
|
||||
- gboolean is_initial;
|
||||
|
||||
/* 0 is root user; since the daemon talks to the session object
|
||||
* directly, itself, for automatic login
|
||||
*/
|
||||
session = create_user_session_for_display (manager, display, 0);
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
- "is-initial", &is_initial,
|
||||
"session-type", &display_session_type,
|
||||
NULL);
|
||||
|
||||
g_object_set (G_OBJECT (session),
|
||||
- "display-is-initial", is_initial,
|
||||
+ "display-is-initial", FALSE,
|
||||
NULL);
|
||||
|
||||
g_debug ("GdmManager: Starting automatic login conversation");
|
||||
gdm_session_start_conversation (session, "gdm-autologin");
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_chooser_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
const char *allowed_user;
|
||||
struct passwd *passwd_entry;
|
||||
|
||||
allowed_user = get_username_for_greeter_display (manager, display);
|
||||
|
||||
if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
|
||||
g_warning ("GdmManager: couldn't look up username %s",
|
||||
allowed_user);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
return;
|
||||
}
|
||||
|
||||
gdm_display_start_greeter_session (display);
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_greeter_session (GdmManager *manager,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,110 @@
|
||||
From 2843a951ef826afd01fa3c7340780b1929db38c7 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 4 Sep 2018 08:12:34 +0200
|
||||
Subject: [PATCH 35/51] local-display-factory: Remove initial VT is in use
|
||||
check
|
||||
|
||||
The initial VT is in use check in on_vt_changed() is racy, when switching
|
||||
to VT1 from an active session, on_vt_changed() may run before logind has
|
||||
processed the VT change and then sd_seat_get_active() will return the
|
||||
active session which we are switching away from. This results in the greeter
|
||||
not being started on VT1.
|
||||
|
||||
On my system gdm reliably wins the race resulting in not getting a greeter
|
||||
when manually switching from an active session to VT1.
|
||||
|
||||
gdm already starts the greeter unconditionally from
|
||||
gdm_local_display_factory_sync_seats() on both startup and when an user
|
||||
session exits. gdm also starts it unconditionally when selecting
|
||||
"Switch user" from an user session.
|
||||
|
||||
Now autologin sessions avoid the initial VT as well.
|
||||
|
||||
So we now can assume that the initial VT is free for the login screen's
|
||||
use. And create_display already checks for and re-uses
|
||||
an existing greeter, so we can safely remove the racy check.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 13 -------------
|
||||
1 file changed, 13 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 13d56dcff..8e46dbca2 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -752,73 +752,60 @@ on_vt_changed (GIOChannel *source,
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
||||
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
|
||||
if (display != NULL)
|
||||
maybe_stop_greeter_in_background (factory, display);
|
||||
} else {
|
||||
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if user jumped back to initial vt and it's empty put a login screen
|
||||
* on it (unless a login screen is already running elsewhere, then
|
||||
* jump to that login screen)
|
||||
*/
|
||||
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
- ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
||||
-
|
||||
- if (ret == 0) {
|
||||
- g_autofree char *state = NULL;
|
||||
- ret = sd_session_get_state (active_session_id, &state);
|
||||
-
|
||||
- /* if there's something already running on the active VT then bail */
|
||||
- if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
|
||||
- g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
|
||||
- return G_SOURCE_CONTINUE;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
session_type = "wayland";
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
|
||||
|
||||
create_display (factory, "seat0", session_type, TRUE);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
g_autoptr (GIOChannel) io_channel = NULL;
|
||||
|
||||
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatNew",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_seat_new,
|
||||
g_object_ref (factory),
|
||||
g_object_unref);
|
||||
factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatRemoved",
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,140 @@
|
||||
From f5acee2766c05403235c06da6b1bb68af744da79 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 25 Sep 2018 14:30:16 -0400
|
||||
Subject: [PATCH 36/51] local-display-factory: Remove same VT so don't switch
|
||||
check
|
||||
|
||||
We avoid changing to the login screen vt if we're already on it,
|
||||
but the call is racy since we react to vt changes concurrently
|
||||
with logind (who we query for the active vt).
|
||||
|
||||
This check drops the active vt check since it's pointless and
|
||||
getting in the way.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 39 ++++++++++--------------------
|
||||
1 file changed, 13 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 8e46dbca2..be7b43cff 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -410,103 +410,90 @@ lookup_by_seat_id (const char *id,
|
||||
res = g_strcmp0 (current, looking_for) == 0;
|
||||
|
||||
g_free(current);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
lookup_prepared_display_by_seat_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
int status;
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
if (status != GDM_DISPLAY_PREPARED)
|
||||
return FALSE;
|
||||
|
||||
return lookup_by_seat_id (id, display, user_data);
|
||||
}
|
||||
|
||||
static GdmDisplay *
|
||||
create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
- char *active_session_id = NULL;
|
||||
- int ret;
|
||||
+ g_autofree char *login_session_id = NULL;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
|
||||
session_type? : "X11", seat_id);
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
if (sd_seat_can_multi_session (seat_id))
|
||||
display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
|
||||
else
|
||||
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
|
||||
/* Ensure we don't create the same display more than once */
|
||||
if (display != NULL) {
|
||||
g_debug ("GdmLocalDisplayFactory: display already created");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
|
||||
-
|
||||
- if (ret == 0) {
|
||||
- char *login_session_id = NULL;
|
||||
-
|
||||
- /* If we already have a login window, switch to it */
|
||||
- if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
- GdmDisplay *display;
|
||||
-
|
||||
- display = gdm_display_store_find (store,
|
||||
- lookup_by_session_id,
|
||||
- (gpointer) login_session_id);
|
||||
- if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
- if (g_strcmp0 (active_session_id, login_session_id) != 0) {
|
||||
- g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
|
||||
- login_session_id);
|
||||
- gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
- }
|
||||
- g_clear_pointer (&login_session_id, g_free);
|
||||
- g_clear_pointer (&active_session_id, g_free);
|
||||
- return NULL;
|
||||
- }
|
||||
- g_clear_pointer (&login_session_id, g_free);
|
||||
+ /* If we already have a login window, switch to it */
|
||||
+ if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
+ GdmDisplay *display;
|
||||
+
|
||||
+ display = gdm_display_store_find (store,
|
||||
+ lookup_by_session_id,
|
||||
+ (gpointer) login_session_id);
|
||||
+ if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
|
||||
+ login_session_id);
|
||||
+ gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
+ return NULL;
|
||||
}
|
||||
- g_clear_pointer (&active_session_id, g_free);
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
|
||||
g_object_set (display, "seat-id", seat_id, NULL);
|
||||
g_object_set (display, "is-initial", initial, NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
/* let store own the ref */
|
||||
g_object_unref (display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,88 @@
|
||||
From 59a4538e335362a92186217be03529f3694697e1 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Tue, 25 Sep 2018 14:39:42 -0400
|
||||
Subject: [PATCH 37/51] local-display-factory: handle reviving displays that
|
||||
are waiting to die
|
||||
|
||||
We may end up re-using a display in waiting-to-finish state before it gets
|
||||
finished in this case reset its state to managed to avoid it getting
|
||||
finished while it is being used.
|
||||
|
||||
Closes https://gitlab.gnome.org/GNOME/gdm/merge_requests/45
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index be7b43cff..d999596b5 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -434,61 +434,64 @@ create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
|
||||
session_type? : "X11", seat_id);
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
|
||||
if (sd_seat_can_multi_session (seat_id))
|
||||
display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
|
||||
else
|
||||
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
|
||||
|
||||
/* Ensure we don't create the same display more than once */
|
||||
if (display != NULL) {
|
||||
g_debug ("GdmLocalDisplayFactory: display already created");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* If we already have a login window, switch to it */
|
||||
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
- if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
+ if (display != NULL &&
|
||||
+ (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED ||
|
||||
+ gdm_display_get_status (display) == GDM_DISPLAY_WAITING_TO_FINISH)) {
|
||||
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL);
|
||||
g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
|
||||
login_session_id);
|
||||
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (seat_id, "seat0") == 0) {
|
||||
display = gdm_local_display_new ();
|
||||
if (session_type != NULL) {
|
||||
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
|
||||
g_object_set (display, "seat-id", seat_id, NULL);
|
||||
g_object_set (display, "is-initial", initial, NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,151 @@
|
||||
From c65a0dbd195be52f0db0c49ea0355fe1b5eb4c09 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 31 Aug 2018 15:48:38 -0400
|
||||
Subject: [PATCH 38/51] manager: don't kill initial-setup before starting user
|
||||
session on wayland
|
||||
|
||||
Right now we kill initial-setup before starting the session for the user
|
||||
initial-setup created. This is the right thing to do for Xorg, since
|
||||
Xorg can't be killed in the background, but it adds unncessary flicker
|
||||
for wayland.
|
||||
|
||||
This commit checks if it's wayland and avoids killing it right away
|
||||
in that case.
|
||||
---
|
||||
daemon/gdm-manager.c | 26 +++++++++++++++++++++-----
|
||||
1 file changed, 21 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index e896c8945..0823e8638 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1639,105 +1639,121 @@ create_display_for_user_session (GdmManager *self,
|
||||
GdmDisplay *display;
|
||||
/* at the moment we only create GdmLocalDisplay objects on seat0 */
|
||||
const char *seat_id = "seat0";
|
||||
|
||||
display = gdm_local_display_new ();
|
||||
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"seat-id", seat_id,
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
gdm_display_store_add (self->priv->display_store,
|
||||
display);
|
||||
g_object_set_data (G_OBJECT (session), "gdm-display", display);
|
||||
g_object_set_data_full (G_OBJECT (display),
|
||||
"gdm-user-session",
|
||||
g_object_ref (session),
|
||||
(GDestroyNotify)
|
||||
clean_user_session);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_start_user_session (StartUserSessionOperation *operation)
|
||||
{
|
||||
GdmManager *self = operation->manager;
|
||||
gboolean migrated;
|
||||
gboolean fail_if_already_switched = TRUE;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
GdmDisplay *display;
|
||||
const char *session_id;
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ g_autofree char *display_session_type = NULL;
|
||||
+#endif
|
||||
|
||||
g_debug ("GdmManager: start or jump to session");
|
||||
|
||||
/* If there's already a session running, jump to it.
|
||||
* If the only session running is the one we just opened,
|
||||
* start a session on it.
|
||||
*/
|
||||
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
|
||||
|
||||
g_debug ("GdmManager: migrated: %d", migrated);
|
||||
if (migrated) {
|
||||
/* We don't stop the manager here because
|
||||
when Xorg exits it switches to the VT it was
|
||||
started from. That interferes with fast
|
||||
user switching. */
|
||||
gdm_session_reset (operation->session);
|
||||
destroy_start_user_session_operation (operation);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display = get_display_for_user_session (operation->session);
|
||||
|
||||
- g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
|
||||
+ g_object_get (G_OBJECT (display),
|
||||
+ "doing-initial-setup", &doing_initial_setup,
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ "session-type", &display_session_type,
|
||||
+#endif
|
||||
+ NULL);
|
||||
|
||||
session_id = gdm_session_get_conversation_session_id (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
|
||||
/* In this case, the greeter's display is morphing into
|
||||
* the user session display. Kill the greeter on this session
|
||||
* and let the user session follow the same display. */
|
||||
gdm_display_stop_greeter_session (display);
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
|
||||
g_object_ref (display);
|
||||
if (doing_initial_setup) {
|
||||
- g_debug ("GdmManager: closing down initial setup display");
|
||||
- gdm_display_stop_greeter_session (display);
|
||||
- gdm_display_unmanage (display);
|
||||
- gdm_display_finish (display);
|
||||
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
+ if (g_strcmp0 (display_session_type, "wayland") == 0) {
|
||||
+ g_debug ("GdmManager: closing down initial setup display in background");
|
||||
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
+ }
|
||||
+#endif
|
||||
+ if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
+ g_debug ("GdmManager: closing down initial setup display");
|
||||
+ gdm_display_stop_greeter_session (display);
|
||||
+ gdm_display_unmanage (display);
|
||||
+ gdm_display_finish (display);
|
||||
+ }
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
session_id);
|
||||
|
||||
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
!gdm_session_client_is_connected (operation->session)) {
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
|
||||
self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
|
||||
g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
|
||||
}
|
||||
}
|
||||
|
||||
start_user_session (operation->manager, operation);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,694 @@
|
||||
From c08afca0807d8820030c19a40e7590f72878c788 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 6 Sep 2018 19:31:50 -0400
|
||||
Subject: [PATCH 39/51] manager: do initial-setup post work in manager code
|
||||
|
||||
Right now we do the initial-setup related post work
|
||||
when stopping the greeter, but the problem is we delay
|
||||
stopping the greeter now until after the user session
|
||||
is started.
|
||||
|
||||
That post-work needs to be done before the user session
|
||||
is started.
|
||||
|
||||
This commit moves the code to a more logical place.
|
||||
---
|
||||
daemon/gdm-display.c | 132 -------------------------------------------
|
||||
daemon/gdm-manager.c | 132 +++++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 132 insertions(+), 132 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
|
||||
index 875534272..1cef8c7c1 100644
|
||||
--- a/daemon/gdm-display.c
|
||||
+++ b/daemon/gdm-display.c
|
||||
@@ -22,61 +22,60 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <xcb/xcb.h>
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
#include "gdm-common.h"
|
||||
#include "gdm-display.h"
|
||||
#include "gdm-display-glue.h"
|
||||
#include "gdm-display-access-file.h"
|
||||
#include "gdm-launch-environment.h"
|
||||
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-settings-keys.h"
|
||||
|
||||
#include "gdm-launch-environment.h"
|
||||
#include "gdm-dbus-util.h"
|
||||
|
||||
-#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
|
||||
#define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
|
||||
|
||||
#define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
|
||||
|
||||
struct GdmDisplayPrivate
|
||||
{
|
||||
char *id;
|
||||
char *seat_id;
|
||||
char *session_id;
|
||||
char *session_class;
|
||||
char *session_type;
|
||||
|
||||
char *remote_hostname;
|
||||
int x11_display_number;
|
||||
char *x11_display_name;
|
||||
int status;
|
||||
time_t creation_time;
|
||||
GTimer *server_timer;
|
||||
|
||||
char *x11_cookie;
|
||||
gsize x11_cookie_size;
|
||||
GdmDisplayAccessFile *access_file;
|
||||
|
||||
guint finish_idle_id;
|
||||
|
||||
xcb_connection_t *xcb_connection;
|
||||
int xcb_screen_number;
|
||||
|
||||
GDBusConnection *connection;
|
||||
GdmDisplayAccessFile *user_access_file;
|
||||
@@ -98,131 +97,60 @@ enum {
|
||||
PROP_0,
|
||||
PROP_ID,
|
||||
PROP_STATUS,
|
||||
PROP_SEAT_ID,
|
||||
PROP_SESSION_ID,
|
||||
PROP_SESSION_CLASS,
|
||||
PROP_SESSION_TYPE,
|
||||
PROP_REMOTE_HOSTNAME,
|
||||
PROP_X11_DISPLAY_NUMBER,
|
||||
PROP_X11_DISPLAY_NAME,
|
||||
PROP_X11_COOKIE,
|
||||
PROP_X11_AUTHORITY_FILE,
|
||||
PROP_IS_CONNECTED,
|
||||
PROP_IS_LOCAL,
|
||||
PROP_LAUNCH_ENVIRONMENT,
|
||||
PROP_IS_INITIAL,
|
||||
PROP_ALLOW_TIMED_LOGIN,
|
||||
PROP_HAVE_EXISTING_USER_ACCOUNTS,
|
||||
PROP_DOING_INITIAL_SETUP,
|
||||
};
|
||||
|
||||
static void gdm_display_class_init (GdmDisplayClass *klass);
|
||||
static void gdm_display_init (GdmDisplay *self);
|
||||
static void gdm_display_finalize (GObject *object);
|
||||
static void queue_finish (GdmDisplay *self);
|
||||
static void _gdm_display_set_status (GdmDisplay *self,
|
||||
int status);
|
||||
static gboolean wants_initial_setup (GdmDisplay *self);
|
||||
G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
|
||||
|
||||
-static gboolean
|
||||
-chown_file (GFile *file,
|
||||
- uid_t uid,
|
||||
- gid_t gid,
|
||||
- GError **error)
|
||||
-{
|
||||
- if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
|
||||
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
- NULL, error)) {
|
||||
- return FALSE;
|
||||
- }
|
||||
- if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
|
||||
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
- NULL, error)) {
|
||||
- return FALSE;
|
||||
- }
|
||||
- return TRUE;
|
||||
-}
|
||||
-
|
||||
-static gboolean
|
||||
-chown_recursively (GFile *dir,
|
||||
- uid_t uid,
|
||||
- gid_t gid,
|
||||
- GError **error)
|
||||
-{
|
||||
- GFile *file = NULL;
|
||||
- GFileInfo *info = NULL;
|
||||
- GFileEnumerator *enumerator = NULL;
|
||||
- gboolean retval = FALSE;
|
||||
-
|
||||
- if (chown_file (dir, uid, gid, error) == FALSE) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- enumerator = g_file_enumerate_children (dir,
|
||||
- G_FILE_ATTRIBUTE_STANDARD_TYPE","
|
||||
- G_FILE_ATTRIBUTE_STANDARD_NAME,
|
||||
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
- NULL, error);
|
||||
- if (!enumerator) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
|
||||
- file = g_file_get_child (dir, g_file_info_get_name (info));
|
||||
-
|
||||
- if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
|
||||
- if (chown_recursively (file, uid, gid, error) == FALSE) {
|
||||
- goto out;
|
||||
- }
|
||||
- } else if (chown_file (file, uid, gid, error) == FALSE) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- g_clear_object (&file);
|
||||
- g_clear_object (&info);
|
||||
- }
|
||||
-
|
||||
- if (*error) {
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- retval = TRUE;
|
||||
-out:
|
||||
- g_clear_object (&file);
|
||||
- g_clear_object (&info);
|
||||
- g_clear_object (&enumerator);
|
||||
-
|
||||
- return retval;
|
||||
-}
|
||||
-
|
||||
GQuark
|
||||
gdm_display_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
if (ret == 0) {
|
||||
ret = g_quark_from_static_string ("gdm_display_error");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_t
|
||||
gdm_display_get_creation_time (GdmDisplay *self)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
|
||||
|
||||
return self->priv->creation_time;
|
||||
}
|
||||
|
||||
int
|
||||
gdm_display_get_status (GdmDisplay *self)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
|
||||
|
||||
return self->priv->status;
|
||||
}
|
||||
|
||||
const char *
|
||||
gdm_display_get_session_id (GdmDisplay *self)
|
||||
{
|
||||
@@ -1649,145 +1577,85 @@ gdm_display_start_greeter_session (GdmDisplay *self)
|
||||
G_CALLBACK (on_launch_environment_session_stopped),
|
||||
self, 0);
|
||||
g_signal_connect_object (self->priv->launch_environment,
|
||||
"exited",
|
||||
G_CALLBACK (on_launch_environment_session_exited),
|
||||
self, 0);
|
||||
g_signal_connect_object (self->priv->launch_environment,
|
||||
"died",
|
||||
G_CALLBACK (on_launch_environment_session_died),
|
||||
self, 0);
|
||||
|
||||
if (auth_file != NULL) {
|
||||
g_object_set (self->priv->launch_environment,
|
||||
"x11-authority-file", auth_file,
|
||||
NULL);
|
||||
}
|
||||
|
||||
gdm_launch_environment_start (self->priv->launch_environment);
|
||||
|
||||
session = gdm_launch_environment_get_session (self->priv->launch_environment);
|
||||
g_object_set (G_OBJECT (session),
|
||||
"display-is-initial", self->priv->is_initial,
|
||||
NULL);
|
||||
|
||||
g_free (display_name);
|
||||
g_free (seat_id);
|
||||
g_free (hostname);
|
||||
g_free (auth_file);
|
||||
}
|
||||
|
||||
-static void
|
||||
-chown_initial_setup_home_dir (void)
|
||||
-{
|
||||
- GFile *dir;
|
||||
- GError *error;
|
||||
- char *gis_dir_path;
|
||||
- char *gis_uid_path;
|
||||
- char *gis_uid_contents;
|
||||
- struct passwd *pwe;
|
||||
- uid_t uid;
|
||||
-
|
||||
- if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
|
||||
- g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- gis_dir_path = g_strdup (pwe->pw_dir);
|
||||
-
|
||||
- gis_uid_path = g_build_filename (gis_dir_path,
|
||||
- "gnome-initial-setup-uid",
|
||||
- NULL);
|
||||
- if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
|
||||
- g_warning ("Unable to read %s", gis_uid_path);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- uid = (uid_t) atoi (gis_uid_contents);
|
||||
- pwe = getpwuid (uid);
|
||||
- if (uid == 0 || pwe == NULL) {
|
||||
- g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- error = NULL;
|
||||
- dir = g_file_new_for_path (gis_dir_path);
|
||||
- if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
|
||||
- g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
|
||||
- g_error_free (error);
|
||||
- }
|
||||
- g_object_unref (dir);
|
||||
-out:
|
||||
- g_free (gis_uid_contents);
|
||||
- g_free (gis_uid_path);
|
||||
- g_free (gis_dir_path);
|
||||
-}
|
||||
-
|
||||
void
|
||||
gdm_display_stop_greeter_session (GdmDisplay *self)
|
||||
{
|
||||
GError *error = NULL;
|
||||
|
||||
if (self->priv->launch_environment != NULL) {
|
||||
|
||||
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
|
||||
G_CALLBACK (on_launch_environment_session_opened),
|
||||
self);
|
||||
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
|
||||
G_CALLBACK (on_launch_environment_session_started),
|
||||
self);
|
||||
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
|
||||
G_CALLBACK (on_launch_environment_session_stopped),
|
||||
self);
|
||||
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
|
||||
G_CALLBACK (on_launch_environment_session_exited),
|
||||
self);
|
||||
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
|
||||
G_CALLBACK (on_launch_environment_session_died),
|
||||
self);
|
||||
gdm_launch_environment_stop (self->priv->launch_environment);
|
||||
g_clear_object (&self->priv->launch_environment);
|
||||
}
|
||||
-
|
||||
- if (self->priv->doing_initial_setup) {
|
||||
- chown_initial_setup_home_dir ();
|
||||
-
|
||||
- if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
|
||||
- "1",
|
||||
- 1,
|
||||
- &error)) {
|
||||
- g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
|
||||
- ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
|
||||
- error->message);
|
||||
- g_clear_error (&error);
|
||||
- }
|
||||
- }
|
||||
}
|
||||
|
||||
static xcb_window_t
|
||||
get_root_window (xcb_connection_t *connection,
|
||||
int screen_number)
|
||||
{
|
||||
xcb_screen_t *screen = NULL;
|
||||
xcb_screen_iterator_t iter;
|
||||
|
||||
iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
|
||||
while (iter.rem) {
|
||||
if (screen_number == 0)
|
||||
screen = iter.data;
|
||||
screen_number--;
|
||||
xcb_screen_next (&iter);
|
||||
}
|
||||
|
||||
if (screen != NULL) {
|
||||
return screen->root;
|
||||
}
|
||||
|
||||
return XCB_WINDOW_NONE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_display_set_windowpath (GdmDisplay *self)
|
||||
{
|
||||
/* setting WINDOWPATH for clients */
|
||||
xcb_intern_atom_cookie_t atom_cookie;
|
||||
xcb_intern_atom_reply_t *atom_reply = NULL;
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index 0823e8638..cf982870c 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -35,60 +35,61 @@
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <act/act-user-manager.h>
|
||||
|
||||
#include <systemd/sd-login.h>
|
||||
|
||||
#include "gdm-common.h"
|
||||
|
||||
#include "gdm-dbus-util.h"
|
||||
#include "gdm-manager.h"
|
||||
#include "gdm-manager-glue.h"
|
||||
#include "gdm-display-store.h"
|
||||
#include "gdm-display-factory.h"
|
||||
#include "gdm-launch-environment.h"
|
||||
#include "gdm-local-display.h"
|
||||
#include "gdm-local-display-factory.h"
|
||||
#include "gdm-session.h"
|
||||
#include "gdm-session-record.h"
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-settings-keys.h"
|
||||
#include "gdm-xdmcp-display-factory.h"
|
||||
#include "gdm-xdmcp-chooser-display.h"
|
||||
|
||||
#define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
|
||||
|
||||
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
||||
#define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager"
|
||||
#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
|
||||
|
||||
#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
|
||||
+#define ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT GDM_RUN_DIR "/gdm.ran-initial-setup"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdmManager *manager;
|
||||
GdmSession *session;
|
||||
char *service_name;
|
||||
guint idle_id;
|
||||
} StartUserSessionOperation;
|
||||
|
||||
struct GdmManagerPrivate
|
||||
{
|
||||
GdmDisplayStore *display_store;
|
||||
GdmLocalDisplayFactory *local_factory;
|
||||
#ifdef HAVE_LIBXDMCP
|
||||
GdmXdmcpDisplayFactory *xdmcp_factory;
|
||||
#endif
|
||||
GdmDisplay *automatic_login_display;
|
||||
GList *user_sessions;
|
||||
GHashTable *transient_sessions;
|
||||
GHashTable *open_reauthentication_requests;
|
||||
gboolean xdmcp_enabled;
|
||||
|
||||
gboolean started;
|
||||
gboolean show_local_greeter;
|
||||
|
||||
GDBusConnection *connection;
|
||||
GDBusObjectManagerServer *object_manager;
|
||||
|
||||
#ifdef WITH_PLYMOUTH
|
||||
guint plymouth_is_running : 1;
|
||||
@@ -1630,130 +1631,261 @@ start_user_session (GdmManager *manager,
|
||||
|
||||
destroy_start_user_session_operation (operation);
|
||||
}
|
||||
|
||||
static void
|
||||
create_display_for_user_session (GdmManager *self,
|
||||
GdmSession *session,
|
||||
const char *session_id)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
/* at the moment we only create GdmLocalDisplay objects on seat0 */
|
||||
const char *seat_id = "seat0";
|
||||
|
||||
display = gdm_local_display_new ();
|
||||
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"seat-id", seat_id,
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
gdm_display_store_add (self->priv->display_store,
|
||||
display);
|
||||
g_object_set_data (G_OBJECT (session), "gdm-display", display);
|
||||
g_object_set_data_full (G_OBJECT (display),
|
||||
"gdm-user-session",
|
||||
g_object_ref (session),
|
||||
(GDestroyNotify)
|
||||
clean_user_session);
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+chown_file (GFile *file,
|
||||
+ uid_t uid,
|
||||
+ gid_t gid,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
|
||||
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
+ NULL, error)) {
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
|
||||
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
+ NULL, error)) {
|
||||
+ return FALSE;
|
||||
+ }
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
+static gboolean
|
||||
+chown_recursively (GFile *dir,
|
||||
+ uid_t uid,
|
||||
+ gid_t gid,
|
||||
+ GError **error)
|
||||
+{
|
||||
+ GFile *file = NULL;
|
||||
+ GFileInfo *info = NULL;
|
||||
+ GFileEnumerator *enumerator = NULL;
|
||||
+ gboolean retval = FALSE;
|
||||
+
|
||||
+ if (chown_file (dir, uid, gid, error) == FALSE) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ enumerator = g_file_enumerate_children (dir,
|
||||
+ G_FILE_ATTRIBUTE_STANDARD_TYPE","
|
||||
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
|
||||
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
+ NULL, error);
|
||||
+ if (!enumerator) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
|
||||
+ file = g_file_get_child (dir, g_file_info_get_name (info));
|
||||
+
|
||||
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
|
||||
+ if (chown_recursively (file, uid, gid, error) == FALSE) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+ } else if (chown_file (file, uid, gid, error) == FALSE) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ g_clear_object (&file);
|
||||
+ g_clear_object (&info);
|
||||
+ }
|
||||
+
|
||||
+ if (*error) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ retval = TRUE;
|
||||
+out:
|
||||
+ g_clear_object (&file);
|
||||
+ g_clear_object (&info);
|
||||
+ g_clear_object (&enumerator);
|
||||
+
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+chown_initial_setup_home_dir (void)
|
||||
+{
|
||||
+ GFile *dir;
|
||||
+ GError *error;
|
||||
+ char *gis_dir_path;
|
||||
+ char *gis_uid_path;
|
||||
+ char *gis_uid_contents;
|
||||
+ struct passwd *pwe;
|
||||
+ uid_t uid;
|
||||
+
|
||||
+ if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
|
||||
+ g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ gis_dir_path = g_strdup (pwe->pw_dir);
|
||||
+
|
||||
+ gis_uid_path = g_build_filename (gis_dir_path,
|
||||
+ "gnome-initial-setup-uid",
|
||||
+ NULL);
|
||||
+ if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
|
||||
+ g_warning ("Unable to read %s", gis_uid_path);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ uid = (uid_t) atoi (gis_uid_contents);
|
||||
+ pwe = getpwuid (uid);
|
||||
+ if (uid == 0 || pwe == NULL) {
|
||||
+ g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ error = NULL;
|
||||
+ dir = g_file_new_for_path (gis_dir_path);
|
||||
+ if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
|
||||
+ g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
|
||||
+ g_error_free (error);
|
||||
+ }
|
||||
+ g_object_unref (dir);
|
||||
+out:
|
||||
+ g_free (gis_uid_contents);
|
||||
+ g_free (gis_uid_path);
|
||||
+ g_free (gis_dir_path);
|
||||
+}
|
||||
+
|
||||
static gboolean
|
||||
on_start_user_session (StartUserSessionOperation *operation)
|
||||
{
|
||||
GdmManager *self = operation->manager;
|
||||
gboolean migrated;
|
||||
gboolean fail_if_already_switched = TRUE;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
GdmDisplay *display;
|
||||
const char *session_id;
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
g_autofree char *display_session_type = NULL;
|
||||
#endif
|
||||
|
||||
g_debug ("GdmManager: start or jump to session");
|
||||
|
||||
/* If there's already a session running, jump to it.
|
||||
* If the only session running is the one we just opened,
|
||||
* start a session on it.
|
||||
*/
|
||||
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
|
||||
|
||||
g_debug ("GdmManager: migrated: %d", migrated);
|
||||
if (migrated) {
|
||||
/* We don't stop the manager here because
|
||||
when Xorg exits it switches to the VT it was
|
||||
started from. That interferes with fast
|
||||
user switching. */
|
||||
gdm_session_reset (operation->session);
|
||||
destroy_start_user_session_operation (operation);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display = get_display_for_user_session (operation->session);
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
"session-type", &display_session_type,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
session_id = gdm_session_get_conversation_session_id (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
|
||||
/* In this case, the greeter's display is morphing into
|
||||
* the user session display. Kill the greeter on this session
|
||||
* and let the user session follow the same display. */
|
||||
gdm_display_stop_greeter_session (display);
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
|
||||
g_object_ref (display);
|
||||
if (doing_initial_setup) {
|
||||
+ g_autoptr(GError) error = NULL;
|
||||
+
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
if (g_strcmp0 (display_session_type, "wayland") == 0) {
|
||||
g_debug ("GdmManager: closing down initial setup display in background");
|
||||
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
}
|
||||
#endif
|
||||
if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
g_debug ("GdmManager: closing down initial setup display");
|
||||
gdm_display_stop_greeter_session (display);
|
||||
gdm_display_unmanage (display);
|
||||
gdm_display_finish (display);
|
||||
}
|
||||
+
|
||||
+ chown_initial_setup_home_dir ();
|
||||
+
|
||||
+ if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
|
||||
+ "1",
|
||||
+ 1,
|
||||
+ &error)) {
|
||||
+ g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
|
||||
+ ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
|
||||
+ error->message);
|
||||
+ g_clear_error (&error);
|
||||
+ }
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
session_id);
|
||||
|
||||
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
!gdm_session_client_is_connected (operation->session)) {
|
||||
/* remove the unused prepared greeter display since we're not going
|
||||
* to have a greeter */
|
||||
gdm_display_store_remove (self->priv->display_store, display);
|
||||
g_object_unref (display);
|
||||
|
||||
self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
|
||||
g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
|
||||
}
|
||||
}
|
||||
|
||||
start_user_session (operation->manager, operation);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,117 @@
|
||||
From 49383786d96414e7204ea50ca5ea0263be97b581 Mon Sep 17 00:00:00 2001
|
||||
From: xiaoguang wang <xwang@suse.com>
|
||||
Date: Wed, 20 Feb 2019 09:26:02 +0800
|
||||
Subject: [PATCH 40/51] display-store: make foreach ignore callback return
|
||||
value
|
||||
|
||||
gdm_display_store_foreach is designed to iterate through all
|
||||
displays in the display store. Under the hood, it currently
|
||||
uses gdm_display_store_find, though, so will prematurely stop
|
||||
it's loop if a callback returns TRUE. Callers are getting this
|
||||
wrong. Some return TRUE with the expectation it goes on, and
|
||||
some fail to return a value at all.
|
||||
|
||||
This commit changes gdm_display_store_foreach to use
|
||||
g_hash_table_foreach instead, so the callback return values no
|
||||
longer matter.
|
||||
---
|
||||
daemon/gdm-display-store.c | 16 +++++++++++++---
|
||||
1 file changed, 13 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-display-store.c b/daemon/gdm-display-store.c
|
||||
index fd24334eb..910468cd7 100644
|
||||
--- a/daemon/gdm-display-store.c
|
||||
+++ b/daemon/gdm-display-store.c
|
||||
@@ -119,76 +119,86 @@ remove_display (char *id,
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_display_store_remove (GdmDisplayStore *store,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
g_return_val_if_fail (store != NULL, FALSE);
|
||||
|
||||
gdm_display_store_foreach_remove (store,
|
||||
(GdmDisplayStoreFunc)remove_display,
|
||||
display);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GdmDisplayStoreFunc predicate;
|
||||
gpointer user_data;
|
||||
} FindClosure;
|
||||
|
||||
static gboolean
|
||||
find_func (const char *id,
|
||||
StoredDisplay *stored_display,
|
||||
FindClosure *closure)
|
||||
{
|
||||
return closure->predicate (id,
|
||||
stored_display->display,
|
||||
closure->user_data);
|
||||
}
|
||||
|
||||
+static void
|
||||
+foreach_func (const char *id,
|
||||
+ StoredDisplay *stored_display,
|
||||
+ FindClosure *closure)
|
||||
+{
|
||||
+ (void) closure->predicate (id,
|
||||
+ stored_display->display,
|
||||
+ closure->user_data);
|
||||
+}
|
||||
+
|
||||
void
|
||||
gdm_display_store_foreach (GdmDisplayStore *store,
|
||||
GdmDisplayStoreFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
FindClosure closure;
|
||||
|
||||
g_return_if_fail (store != NULL);
|
||||
g_return_if_fail (func != NULL);
|
||||
|
||||
closure.predicate = func;
|
||||
closure.user_data = user_data;
|
||||
|
||||
- g_hash_table_find (store->priv->displays,
|
||||
- (GHRFunc) find_func,
|
||||
- &closure);
|
||||
+ g_hash_table_foreach (store->priv->displays,
|
||||
+ (GHFunc) foreach_func,
|
||||
+ &closure);
|
||||
}
|
||||
|
||||
GdmDisplay *
|
||||
gdm_display_store_lookup (GdmDisplayStore *store,
|
||||
const char *id)
|
||||
{
|
||||
StoredDisplay *stored_display;
|
||||
|
||||
g_return_val_if_fail (store != NULL, NULL);
|
||||
g_return_val_if_fail (id != NULL, NULL);
|
||||
|
||||
stored_display = g_hash_table_lookup (store->priv->displays,
|
||||
id);
|
||||
if (stored_display == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return stored_display->display;
|
||||
}
|
||||
|
||||
GdmDisplay *
|
||||
gdm_display_store_find (GdmDisplayStore *store,
|
||||
GdmDisplayStoreFunc predicate,
|
||||
gpointer user_data)
|
||||
{
|
||||
StoredDisplay *stored_display;
|
||||
FindClosure closure;
|
||||
|
||||
g_return_val_if_fail (store != NULL, NULL);
|
||||
g_return_val_if_fail (predicate != NULL, NULL);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,180 @@
|
||||
From 323358ef61d969588ea048d5b0eba6fd102d3dcf Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 21 Feb 2019 15:20:01 -0500
|
||||
Subject: [PATCH 41/51] xdmcp-display-factory: don't return value from foreach
|
||||
funcs
|
||||
|
||||
The xdmcp code is returning TRUE from its display store foreach
|
||||
functions, which is useless since commit 47d01abe and wrong
|
||||
before that.
|
||||
|
||||
This commit makes it return void instead.
|
||||
---
|
||||
daemon/gdm-xdmcp-display-factory.c | 8 ++------
|
||||
1 file changed, 2 insertions(+), 6 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
|
||||
index 5b5786c6f..2e14beab4 100644
|
||||
--- a/daemon/gdm-xdmcp-display-factory.c
|
||||
+++ b/daemon/gdm-xdmcp-display-factory.c
|
||||
@@ -639,76 +639,74 @@ gdm_xdmcp_host_allow (GdmAddress *address)
|
||||
{
|
||||
#ifdef HAVE_TCPWRAPPERS
|
||||
char *client;
|
||||
char *host;
|
||||
gboolean ret;
|
||||
|
||||
host = NULL;
|
||||
client = NULL;
|
||||
|
||||
/* Find client hostname */
|
||||
gdm_address_get_hostname (address, &client);
|
||||
gdm_address_get_numeric_info (address, &host, NULL);
|
||||
|
||||
/* Check with tcp_wrappers if client is allowed to access */
|
||||
ret = hosts_ctl ("gdm", client, host, "");
|
||||
|
||||
g_free (host);
|
||||
g_free (client);
|
||||
|
||||
return ret;
|
||||
#else /* HAVE_TCPWRAPPERS */
|
||||
return (TRUE);
|
||||
#endif /* HAVE_TCPWRAPPERS */
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GdmAddress *address;
|
||||
int count;
|
||||
} CountDisplayData;
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
count_displays_from_host (const char *id,
|
||||
GdmDisplay *display,
|
||||
CountDisplayData *data)
|
||||
{
|
||||
GdmAddress *address;
|
||||
|
||||
if (GDM_IS_XDMCP_DISPLAY (display)) {
|
||||
address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
|
||||
|
||||
if (gdm_address_equal (address, data->address)) {
|
||||
data->count++;
|
||||
}
|
||||
}
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
gdm_xdmcp_num_displays_from_host (GdmXdmcpDisplayFactory *factory,
|
||||
GdmAddress *address)
|
||||
{
|
||||
CountDisplayData data;
|
||||
GdmDisplayStore *store;
|
||||
|
||||
data.count = 0;
|
||||
data.address = address;
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
gdm_display_store_foreach (store,
|
||||
(GdmDisplayStoreFunc)count_displays_from_host,
|
||||
&data);
|
||||
|
||||
return data.count;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
GdmAddress *address;
|
||||
int display_num;
|
||||
} LookupHostData;
|
||||
|
||||
static gboolean
|
||||
lookup_by_host (const char *id,
|
||||
GdmDisplay *display,
|
||||
LookupHostData *data)
|
||||
{
|
||||
@@ -1780,78 +1778,76 @@ gdm_xdmcp_send_managed_forward (GdmXdmcpDisplayFactory *factory,
|
||||
|
||||
static void
|
||||
gdm_xdmcp_send_got_managed_forward (GdmXdmcpDisplayFactory *factory,
|
||||
GdmAddress *address,
|
||||
GdmAddress *origin)
|
||||
{
|
||||
ARRAY8 addr;
|
||||
XdmcpHeader header;
|
||||
char *host;
|
||||
|
||||
host = NULL;
|
||||
gdm_address_get_numeric_info (address, &host, NULL);
|
||||
g_debug ("GdmXdmcpDisplayFactory: Sending GOT_MANAGED_FORWARD to %s",
|
||||
host ? host : "(null)");
|
||||
g_free (host);
|
||||
|
||||
set_address_for_request (origin, &addr);
|
||||
|
||||
header.opcode = (CARD16) GDM_XDMCP_GOT_MANAGED_FORWARD;
|
||||
header.length = 4 + addr.length;
|
||||
header.version = GDM_XDMCP_PROTOCOL_VERSION;
|
||||
XdmcpWriteHeader (&factory->priv->buf, &header);
|
||||
|
||||
XdmcpWriteARRAY8 (&factory->priv->buf, &addr);
|
||||
XdmcpFlush (factory->priv->socket_fd,
|
||||
&factory->priv->buf,
|
||||
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
|
||||
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
|
||||
}
|
||||
|
||||
-static gboolean
|
||||
+static void
|
||||
count_sessions (const char *id,
|
||||
GdmDisplay *display,
|
||||
GdmXdmcpDisplayFactory *factory)
|
||||
{
|
||||
if (GDM_IS_XDMCP_DISPLAY (display)) {
|
||||
int status;
|
||||
|
||||
status = gdm_display_get_status (display);
|
||||
|
||||
if (status == GDM_DISPLAY_MANAGED) {
|
||||
factory->priv->num_sessions++;
|
||||
} else if (status == GDM_DISPLAY_UNMANAGED) {
|
||||
factory->priv->num_pending_sessions++;
|
||||
}
|
||||
}
|
||||
-
|
||||
- return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_xdmcp_recount_sessions (GdmXdmcpDisplayFactory *factory)
|
||||
{
|
||||
GdmDisplayStore *store;
|
||||
|
||||
factory->priv->num_sessions = 0;
|
||||
factory->priv->num_pending_sessions = 0;
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
gdm_display_store_foreach (store,
|
||||
(GdmDisplayStoreFunc)count_sessions,
|
||||
factory);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
purge_displays (const char *id,
|
||||
GdmDisplay *display,
|
||||
GdmXdmcpDisplayFactory *factory)
|
||||
{
|
||||
if (GDM_IS_XDMCP_DISPLAY (display)) {
|
||||
int status;
|
||||
time_t currtime;
|
||||
time_t acctime;
|
||||
|
||||
currtime = time (NULL);
|
||||
status = gdm_display_get_status (display);
|
||||
acctime = gdm_display_get_creation_time (display);
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,538 @@
|
||||
From 3cf5b4b12d3d39fa858ff593adeecfe711cdddaf Mon Sep 17 00:00:00 2001
|
||||
From: Iain Lane <iainl@gnome.org>
|
||||
Date: Tue, 7 May 2019 15:35:23 +0100
|
||||
Subject: [PATCH 42/51] GdmLocalDisplayFactory: Store VT number, not tty
|
||||
identifier
|
||||
|
||||
This makes the code a fair bit simpler.
|
||||
---
|
||||
configure.ac | 6 ++--
|
||||
daemon/gdm-local-display-factory.c | 50 ++++++++++++++++--------------
|
||||
daemon/gdm-server.c | 2 +-
|
||||
daemon/gdm-session-worker.c | 2 +-
|
||||
4 files changed, 31 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index c549146ce..0c138ab38 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -1477,66 +1477,66 @@ fi
|
||||
AC_SUBST(DEBUG_CFLAGS)
|
||||
|
||||
#
|
||||
# Enable Profiling
|
||||
#
|
||||
AC_ARG_ENABLE(profiling,
|
||||
AS_HELP_STRING([--enable-profiling],
|
||||
[turn on profiling]),,
|
||||
enable_profiling=yes)
|
||||
|
||||
if test "$enable_profiling" = "yes"; then
|
||||
AC_DEFINE(ENABLE_PROFILING,1,[enable profiling])
|
||||
fi
|
||||
|
||||
#
|
||||
# Set SHELL to use in scripts.
|
||||
#
|
||||
if test x$os_solaris = xyes ; then
|
||||
XSESSION_SHELL=/bin/ksh
|
||||
else
|
||||
XSESSION_SHELL=/bin/sh
|
||||
fi
|
||||
|
||||
#
|
||||
# Set VT to use for initial server
|
||||
#
|
||||
AC_ARG_WITH(initial-vt,
|
||||
AS_HELP_STRING([--with-initial-vt=<nr>],
|
||||
[Initial virtual terminal to use]))
|
||||
if ! test -z "$with_initial_vt"; then
|
||||
- GDM_INITIAL_VT="$with_initial_vt"
|
||||
+ GDM_INITIAL_VT=$with_initial_vt
|
||||
else
|
||||
- GDM_INITIAL_VT="1"
|
||||
+ GDM_INITIAL_VT=1
|
||||
fi
|
||||
AC_SUBST(GDM_INITIAL_VT)
|
||||
-AC_DEFINE_UNQUOTED(GDM_INITIAL_VT, "$GDM_INITIAL_VT", [Initial Virtual Terminal])
|
||||
+AC_DEFINE_UNQUOTED(GDM_INITIAL_VT, $GDM_INITIAL_VT, [Initial Virtual Terminal])
|
||||
|
||||
# Set configuration choices.
|
||||
#
|
||||
AC_SUBST(XSESSION_SHELL)
|
||||
AC_DEFINE_UNQUOTED(XSESSION_SHELL,"$XSESSION_SHELL",[xsession shell])
|
||||
AC_SUBST(SOUND_PROGRAM)
|
||||
AC_DEFINE_UNQUOTED(SOUND_PROGRAM,"$SOUND_PROGRAM",[])
|
||||
|
||||
AC_SUBST(X_PATH)
|
||||
AC_SUBST(X_SERVER)
|
||||
AC_SUBST(X_SERVER_PATH)
|
||||
AC_DEFINE_UNQUOTED(X_SERVER,"$X_SERVER",[])
|
||||
AC_DEFINE_UNQUOTED(X_SERVER_PATH,"$X_SERVER_PATH",[])
|
||||
|
||||
## Stuff for debian/changelog.in
|
||||
#if test -e "debian/changelog"; then
|
||||
# DEBIAN_DATESTAMP=`head -1 debian/changelog| sed -e 's/.*cvs.//' -e 's/).*//'`
|
||||
# DEBIAN_DATE=`grep '^ --' debian/changelog | head -1 | sed -e 's/.* //'`
|
||||
#else
|
||||
# DEBIAN_DATESTAMP=`date +%Y%m%d%H%M%s`
|
||||
# DEBIAN_DATE=`date -R`
|
||||
#fi
|
||||
#
|
||||
#AC_SUBST(DEBIAN_DATESTAMP)
|
||||
#AC_SUBST(DEBIAN_DATE)
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
pam-extensions/Makefile
|
||||
pam-extensions/gdm-pam-extensions.pc
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index d999596b5..7a013c694 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -37,61 +37,61 @@
|
||||
#include "gdm-local-display-factory-glue.h"
|
||||
|
||||
#include "gdm-settings-keys.h"
|
||||
#include "gdm-settings-direct.h"
|
||||
#include "gdm-display-store.h"
|
||||
#include "gdm-local-display.h"
|
||||
#include "gdm-legacy-display.h"
|
||||
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
||||
|
||||
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
||||
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
||||
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
||||
|
||||
#define MAX_DISPLAY_FAILURES 5
|
||||
#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
|
||||
|
||||
struct GdmLocalDisplayFactoryPrivate
|
||||
{
|
||||
GdmDBusLocalDisplayFactory *skeleton;
|
||||
GDBusConnection *connection;
|
||||
GHashTable *used_display_numbers;
|
||||
|
||||
/* FIXME: this needs to be per seat? */
|
||||
guint num_failures;
|
||||
|
||||
guint seat_new_id;
|
||||
guint seat_removed_id;
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
- char *tty_of_active_vt;
|
||||
+ unsigned int active_vt;
|
||||
guint active_vt_watch_id;
|
||||
guint wait_to_finish_timeout_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
};
|
||||
|
||||
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
|
||||
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
|
||||
static void gdm_local_display_factory_finalize (GObject *object);
|
||||
|
||||
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
|
||||
const char *seat_id,
|
||||
const char *session_type,
|
||||
gboolean initial_display);
|
||||
|
||||
static void on_display_status_changed (GdmDisplay *display,
|
||||
GParamSpec *arg1,
|
||||
GdmLocalDisplayFactory *factory);
|
||||
|
||||
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
|
||||
static gpointer local_display_factory_object = NULL;
|
||||
static gboolean lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data);
|
||||
|
||||
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
||||
|
||||
@@ -641,157 +641,161 @@ maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
|
||||
g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
/* we can only stop greeter for wayland sessions, since
|
||||
* X server would jump back on exit */
|
||||
if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
||||
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
|
||||
/* We stop the greeter after a timeout to avoid flicker */
|
||||
if (factory->priv->wait_to_finish_timeout_id != 0)
|
||||
g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
||||
|
||||
factory->priv->wait_to_finish_timeout_id =
|
||||
g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
|
||||
(GSourceFunc)wait_to_finish_timeout,
|
||||
factory);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_vt_changed (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GIOStatus status;
|
||||
- static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
||||
- g_autofree char *tty_of_previous_vt = NULL;
|
||||
g_autofree char *tty_of_active_vt = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
g_autofree char *active_session_id = NULL;
|
||||
+ unsigned int previous_vt, new_vt;
|
||||
const char *session_type = NULL;
|
||||
- int ret;
|
||||
+ int ret, n_returned;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
||||
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
||||
|
||||
if (condition & G_IO_PRI) {
|
||||
g_autoptr (GError) error = NULL;
|
||||
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
||||
|
||||
if (error != NULL) {
|
||||
g_warning ("could not read active VT from kernel: %s", error->message);
|
||||
}
|
||||
switch (status) {
|
||||
case G_IO_STATUS_ERROR:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_EOF:
|
||||
return G_SOURCE_REMOVE;
|
||||
case G_IO_STATUS_AGAIN:
|
||||
return G_SOURCE_CONTINUE;
|
||||
case G_IO_STATUS_NORMAL:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
|
||||
g_debug ("GdmLocalDisplayFactory: kernel hung up active vt watch");
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
if (tty_of_active_vt == NULL) {
|
||||
g_debug ("GdmLocalDisplayFactory: unable to read active VT from kernel");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
g_strchomp (tty_of_active_vt);
|
||||
|
||||
+ errno = 0;
|
||||
+ n_returned = sscanf (tty_of_active_vt, "tty%u", &new_vt);
|
||||
+
|
||||
+ if (n_returned != 1 || errno != 0) {
|
||||
+ g_critical ("GdmLocalDisplayFactory: Couldn't read active VT (got '%s')",
|
||||
+ tty_of_active_vt);
|
||||
+ return G_SOURCE_CONTINUE;
|
||||
+ }
|
||||
+
|
||||
/* don't do anything if we're on the same VT we were before */
|
||||
- if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0) {
|
||||
+ if (new_vt == factory->priv->active_vt) {
|
||||
g_debug ("GdmLocalDisplayFactory: VT changed to the same VT, ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
- tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
|
||||
- factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
|
||||
+ previous_vt = factory->priv->active_vt;
|
||||
+ factory->priv->active_vt = new_vt;
|
||||
|
||||
/* don't do anything at start up */
|
||||
- if (tty_of_previous_vt == NULL) {
|
||||
- g_debug ("GdmLocalDisplayFactory: VT is %s at startup",
|
||||
- factory->priv->tty_of_active_vt);
|
||||
+ if (previous_vt == 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT is %u at startup",
|
||||
+ factory->priv->active_vt);
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
- g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
||||
- tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT changed from %u to %u",
|
||||
+ previous_vt, factory->priv->active_vt);
|
||||
|
||||
/* if the old VT was running a wayland login screen kill it
|
||||
*/
|
||||
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
||||
- unsigned int vt;
|
||||
+ unsigned int login_window_vt;
|
||||
|
||||
- ret = sd_session_get_vt (login_session_id, &vt);
|
||||
- if (ret == 0 && vt != 0) {
|
||||
- g_autofree char *tty_of_login_window_vt = NULL;
|
||||
-
|
||||
- tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
||||
-
|
||||
- g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
||||
- if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
||||
+ ret = sd_session_get_vt (login_session_id, &login_window_vt);
|
||||
+ if (ret == 0 && login_window_vt != 0) {
|
||||
+ g_debug ("GdmLocalDisplayFactory: VT of login window is %u", login_window_vt);
|
||||
+ if (login_window_vt == previous_vt) {
|
||||
GdmDisplayStore *store;
|
||||
GdmDisplay *display;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
||||
|
||||
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
||||
display = gdm_display_store_find (store,
|
||||
lookup_by_session_id,
|
||||
(gpointer) login_session_id);
|
||||
|
||||
if (display != NULL)
|
||||
maybe_stop_greeter_in_background (factory, display);
|
||||
} else {
|
||||
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if user jumped back to initial vt and it's empty put a login screen
|
||||
* on it (unless a login screen is already running elsewhere, then
|
||||
* jump to that login screen)
|
||||
*/
|
||||
- if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
||||
+ if (factory->priv->active_vt != GDM_INITIAL_VT) {
|
||||
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
session_type = "wayland";
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
|
||||
|
||||
create_display (factory, "seat0", session_type, TRUE);
|
||||
|
||||
return G_SOURCE_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
g_autoptr (GIOChannel) io_channel = NULL;
|
||||
|
||||
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
|
||||
"org.freedesktop.login1",
|
||||
"org.freedesktop.login1.Manager",
|
||||
"SeatNew",
|
||||
"/org/freedesktop/login1",
|
||||
NULL,
|
||||
G_DBUS_SIGNAL_FLAGS_NONE,
|
||||
on_seat_new,
|
||||
g_object_ref (factory),
|
||||
g_object_unref);
|
||||
@@ -815,62 +819,60 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
||||
G_IO_PRI,
|
||||
(GIOFunc)
|
||||
on_vt_changed,
|
||||
factory);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
if (factory->priv->seat_new_id) {
|
||||
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
||||
factory->priv->seat_new_id);
|
||||
factory->priv->seat_new_id = 0;
|
||||
}
|
||||
if (factory->priv->seat_removed_id) {
|
||||
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
||||
factory->priv->seat_removed_id);
|
||||
factory->priv->seat_removed_id = 0;
|
||||
}
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
if (factory->priv->wait_to_finish_timeout_id != 0) {
|
||||
g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
||||
factory->priv->wait_to_finish_timeout_id = 0;
|
||||
}
|
||||
if (factory->priv->active_vt_watch_id) {
|
||||
g_source_remove (factory->priv->active_vt_watch_id);
|
||||
factory->priv->active_vt_watch_id = 0;
|
||||
}
|
||||
-
|
||||
- g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_added (GdmDisplayStore *display_store,
|
||||
const char *id,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GdmDisplay *display;
|
||||
|
||||
display = gdm_display_store_lookup (display_store, id);
|
||||
|
||||
if (display != NULL) {
|
||||
g_signal_connect_object (display, "notify::status",
|
||||
G_CALLBACK (on_display_status_changed),
|
||||
factory,
|
||||
0);
|
||||
|
||||
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_display_removed (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory);
|
||||
g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
||||
}
|
||||
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
|
||||
index 83fba99c8..04406a61a 100644
|
||||
--- a/daemon/gdm-server.c
|
||||
+++ b/daemon/gdm-server.c
|
||||
@@ -726,61 +726,61 @@ gdm_server_spawn (GdmServer *server,
|
||||
(GChildWatchFunc)server_child_watch,
|
||||
server);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
g_strfreev (argv);
|
||||
if (env) {
|
||||
g_ptr_array_foreach (env, (GFunc)g_free, NULL);
|
||||
g_ptr_array_free (env, TRUE);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdm_server_start:
|
||||
* @disp: Pointer to a GdmDisplay structure
|
||||
*
|
||||
* Starts a local X server. Handles retries and fatal errors properly.
|
||||
*/
|
||||
|
||||
gboolean
|
||||
gdm_server_start (GdmServer *server)
|
||||
{
|
||||
gboolean res = FALSE;
|
||||
const char *vtarg = NULL;
|
||||
GError *local_error = NULL;
|
||||
GError **error = &local_error;
|
||||
|
||||
/* Hardcode the VT for the initial X server, but nothing else */
|
||||
if (server->priv->is_initial) {
|
||||
- vtarg = "vt" GDM_INITIAL_VT;
|
||||
+ vtarg = "vt" G_STRINGIFY (GDM_INITIAL_VT);
|
||||
}
|
||||
|
||||
/* fork X server process */
|
||||
if (!gdm_server_spawn (server, vtarg, error)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = TRUE;
|
||||
out:
|
||||
if (local_error) {
|
||||
g_printerr ("%s\n", local_error->message);
|
||||
g_clear_error (&local_error);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void
|
||||
server_died (GdmServer *server)
|
||||
{
|
||||
int exit_status;
|
||||
|
||||
g_debug ("GdmServer: Waiting on process %d", server->priv->pid);
|
||||
exit_status = gdm_wait_on_pid (server->priv->pid);
|
||||
|
||||
if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
|
||||
g_debug ("GdmServer: Wait on child process failed");
|
||||
} else {
|
||||
/* exited normally */
|
||||
}
|
||||
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index 7ed2789da..b4befaa83 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -2202,61 +2202,61 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
|
||||
|
||||
g_debug ("GdmSessionWorker: state SESSION_STARTED");
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
|
||||
|
||||
gdm_session_worker_watch_child (worker);
|
||||
|
||||
out:
|
||||
if (error_code != PAM_SUCCESS) {
|
||||
gdm_session_worker_uninitialize_pam (worker, error_code);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_up_for_new_vt (GdmSessionWorker *worker)
|
||||
{
|
||||
int fd;
|
||||
char vt_string[256], tty_string[256];
|
||||
int session_vt = 0;
|
||||
|
||||
fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (fd < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't open VT master: %m");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (worker->priv->display_is_initial) {
|
||||
- session_vt = atoi (GDM_INITIAL_VT);
|
||||
+ session_vt = GDM_INITIAL_VT;
|
||||
} else {
|
||||
if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't open new VT: %m");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
worker->priv->session_vt = session_vt;
|
||||
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
g_assert (session_vt > 0);
|
||||
|
||||
g_snprintf (vt_string, sizeof (vt_string), "%d", session_vt);
|
||||
|
||||
/* Set the VTNR. This is used by logind to configure a session in
|
||||
* the logind-managed case, but it doesn't hurt to set it always.
|
||||
* When logind gains support for XDG_VTNR=auto, we can make the
|
||||
* OPENQRY and this whole path only used by the new VT code. */
|
||||
gdm_session_worker_set_environment_variable (worker,
|
||||
"XDG_VTNR",
|
||||
vt_string);
|
||||
|
||||
g_snprintf (tty_string, 256, "/dev/tty%d", session_vt);
|
||||
worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
|
||||
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
|
||||
|
||||
return TRUE;
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,344 @@
|
||||
From 476230f7b721781c682d26983c9a2fd82afc45e1 Mon Sep 17 00:00:00 2001
|
||||
From: Benjamin Berg <bberg@redhat.com>
|
||||
Date: Wed, 25 Sep 2019 14:51:40 +0200
|
||||
Subject: [PATCH 43/51] gdm-session-worker: Drop login_vt assuming it is
|
||||
GDM_INITIAL_VT
|
||||
|
||||
When a session ends, its "session worker" is closed. Since
|
||||
3e8220921bb608afd06ed677104fd2244b901a28 (3.33.4), we uninitialise PAM
|
||||
when this happens. As part of this procedure, we jump back to the login
|
||||
screen, if the screen being killed is not itself the login screen.
|
||||
|
||||
This has broken fast user switching. It goes like this - this
|
||||
explanation is a bit complicated, bear with us:
|
||||
|
||||
We want to jump back to the login screen when a normal user session
|
||||
ends, so that people can log in again. We do not want to do this when a
|
||||
login screen itself ends. When session workers start up, they query for
|
||||
the *currently active VT* and save this in `login_vt`. Then later on, we
|
||||
check if our session ID is the same as `login_vt`, and jump to
|
||||
`login_vt` if they are different - this means that it was a user session
|
||||
not a login session. Querying the currently active VT is fine for the
|
||||
first greeter, but when initiating a user switch it's wrong as this
|
||||
gives the user VT.
|
||||
|
||||
GDM greeters are killed once they have spawned a session. They are
|
||||
associated with a logind session, and therefore a PAM session. There are
|
||||
some actions performed when unregistering PAM sessions, including the
|
||||
previously mentioned VT jump. Before
|
||||
3e8220921bb608afd06ed677104fd2244b901a28 we only uninitialised PAM when
|
||||
the session itself exited so the bug was masked, but now (since this
|
||||
commit), if the login screen's *worker* exits first - as happens in the
|
||||
normal case when GDM kills it - we also do this uninitialisation. Since
|
||||
we falsely recorded the login screen as the first user's VT, this means
|
||||
that checking `login_vt != session_vt` returns `TRUE` and we jump back
|
||||
to the previous user's session immediately after logging into the new
|
||||
session: fast user switching is broken.
|
||||
|
||||
Since the work on shutting down the GDM session has been finished, we
|
||||
can assume that the login_vt is always on GDM_INITIAL_VT (see
|
||||
example c71bc5d6c3bc2ec448b5c72ce9a811d9c0c7905e
|
||||
"local-display-factory: Remove initial VT is in use check" and
|
||||
39fb4ff64e6a0653e70a3bfab31da47b49227d59 "manager: don't run autologin
|
||||
display on tty1"). So simply replace all usages of login_vt with
|
||||
GDM_INITIAL_VT to solve the above problem.
|
||||
|
||||
Note that in the case where ENABLE_USER_DISPLAY_SERVER is not enabled,
|
||||
the login_vt is always the same as the session_vt. We can simply remove
|
||||
the VT switching magic there and everything should be working as
|
||||
expected.
|
||||
|
||||
This is a simpler version of the patch by Iain Lane <iainl@gnome.org>,
|
||||
taking into account that we can make the assumption about the login_vt.
|
||||
|
||||
Closes #515
|
||||
---
|
||||
daemon/gdm-session-worker.c | 43 +++++++++----------------------------
|
||||
1 file changed, 10 insertions(+), 33 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index b4befaa83..0bd78cfaf 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -119,61 +119,60 @@ typedef struct
|
||||
|
||||
} ReauthenticationRequest;
|
||||
|
||||
struct GdmSessionWorkerPrivate
|
||||
{
|
||||
GdmSessionWorkerState state;
|
||||
|
||||
int exit_code;
|
||||
|
||||
pam_handle_t *pam_handle;
|
||||
|
||||
GPid child_pid;
|
||||
guint child_watch_id;
|
||||
|
||||
/* from Setup */
|
||||
char *service;
|
||||
char *x11_display_name;
|
||||
char *x11_authority_file;
|
||||
char *display_device;
|
||||
char *display_seat_id;
|
||||
char *hostname;
|
||||
char *username;
|
||||
char *log_file;
|
||||
char *session_id;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
gboolean password_is_required;
|
||||
char **extensions;
|
||||
|
||||
int cred_flags;
|
||||
- int login_vt;
|
||||
int session_vt;
|
||||
int session_tty_fd;
|
||||
|
||||
char **arguments;
|
||||
guint32 cancelled : 1;
|
||||
guint32 timed_out : 1;
|
||||
guint32 is_program_session : 1;
|
||||
guint32 is_reauth_session : 1;
|
||||
guint32 display_is_local : 1;
|
||||
guint32 display_is_initial : 1;
|
||||
guint state_change_idle_id;
|
||||
GdmSessionDisplayMode display_mode;
|
||||
|
||||
char *server_address;
|
||||
GDBusConnection *connection;
|
||||
GdmDBusWorkerManager *manager;
|
||||
|
||||
GHashTable *reauthentication_requests;
|
||||
|
||||
GdmSessionAuditor *auditor;
|
||||
GdmSessionSettings *user_settings;
|
||||
|
||||
GDBusMethodInvocation *pending_invocation;
|
||||
};
|
||||
|
||||
#ifdef SUPPORTS_PAM_EXTENSIONS
|
||||
static char gdm_pam_extension_environment_block[_POSIX_ARG_MAX];
|
||||
|
||||
static const char * const
|
||||
gdm_supported_pam_extensions[] = {
|
||||
@@ -1029,141 +1028,120 @@ gdm_session_worker_set_state (GdmSessionWorker *worker,
|
||||
|
||||
static void
|
||||
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
|
||||
int status)
|
||||
{
|
||||
g_debug ("GdmSessionWorker: uninitializing PAM");
|
||||
|
||||
if (worker->priv->pam_handle == NULL)
|
||||
return;
|
||||
|
||||
gdm_session_worker_get_username (worker, NULL);
|
||||
|
||||
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
|
||||
pam_close_session (worker->priv->pam_handle, 0);
|
||||
gdm_session_auditor_report_logout (worker->priv->auditor);
|
||||
} else {
|
||||
gdm_session_auditor_report_login_failure (worker->priv->auditor,
|
||||
status,
|
||||
pam_strerror (worker->priv->pam_handle, status));
|
||||
}
|
||||
|
||||
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) {
|
||||
pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED);
|
||||
}
|
||||
|
||||
pam_end (worker->priv->pam_handle, status);
|
||||
worker->priv->pam_handle = NULL;
|
||||
|
||||
gdm_session_worker_stop_auditor (worker);
|
||||
|
||||
+ /* If user-display-server is not enabled the login_vt is always
|
||||
+ * identical to the session_vt. So in that case we never need to
|
||||
+ * do a VT switch. */
|
||||
+#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
|
||||
- if (worker->priv->login_vt != worker->priv->session_vt) {
|
||||
- jump_to_vt (worker, worker->priv->login_vt);
|
||||
+ /* Switch to the login VT if we are not the login screen. */
|
||||
+ if (worker->priv->session_vt != GDM_INITIAL_VT) {
|
||||
+ jump_to_vt (worker, GDM_INITIAL_VT);
|
||||
}
|
||||
}
|
||||
+#endif
|
||||
|
||||
- worker->priv->login_vt = 0;
|
||||
worker->priv->session_vt = 0;
|
||||
|
||||
g_debug ("GdmSessionWorker: state NONE");
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE);
|
||||
}
|
||||
|
||||
static char *
|
||||
_get_tty_for_pam (const char *x11_display_name,
|
||||
const char *display_device)
|
||||
{
|
||||
#ifdef __sun
|
||||
return g_strdup (display_device);
|
||||
#else
|
||||
return g_strdup (x11_display_name);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef PAM_XAUTHDATA
|
||||
static struct pam_xauth_data *
|
||||
_get_xauth_for_pam (const char *x11_authority_file)
|
||||
{
|
||||
FILE *fh;
|
||||
Xauth *auth = NULL;
|
||||
struct pam_xauth_data *retval = NULL;
|
||||
gsize len = sizeof (*retval) + 1;
|
||||
|
||||
fh = fopen (x11_authority_file, "r");
|
||||
if (fh) {
|
||||
auth = XauReadAuth (fh);
|
||||
fclose (fh);
|
||||
}
|
||||
if (auth) {
|
||||
len += auth->name_length + auth->data_length;
|
||||
retval = g_malloc0 (len);
|
||||
}
|
||||
if (retval) {
|
||||
retval->namelen = auth->name_length;
|
||||
retval->name = (char *) (retval + 1);
|
||||
memcpy (retval->name, auth->name, auth->name_length);
|
||||
retval->datalen = auth->data_length;
|
||||
retval->data = retval->name + auth->name_length + 1;
|
||||
memcpy (retval->data, auth->data, auth->data_length);
|
||||
}
|
||||
XauDisposeAuth (auth);
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
-static gboolean
|
||||
-ensure_login_vt (GdmSessionWorker *worker)
|
||||
-{
|
||||
- int fd;
|
||||
- struct vt_stat vt_state = { 0 };
|
||||
- gboolean got_login_vt = FALSE;
|
||||
-
|
||||
- fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
-
|
||||
- if (fd < 0) {
|
||||
- g_debug ("GdmSessionWorker: couldn't open VT master: %m");
|
||||
- return FALSE;
|
||||
- }
|
||||
-
|
||||
- if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
|
||||
- g_debug ("GdmSessionWorker: couldn't get current VT: %m");
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- worker->priv->login_vt = vt_state.v_active;
|
||||
- got_login_vt = TRUE;
|
||||
-out:
|
||||
- close (fd);
|
||||
- return got_login_vt;
|
||||
-}
|
||||
-
|
||||
static gboolean
|
||||
gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
|
||||
const char *service,
|
||||
const char * const *extensions,
|
||||
const char *username,
|
||||
const char *hostname,
|
||||
gboolean display_is_local,
|
||||
const char *x11_display_name,
|
||||
const char *x11_authority_file,
|
||||
const char *display_device,
|
||||
const char *seat_id,
|
||||
GError **error)
|
||||
{
|
||||
struct pam_conv pam_conversation;
|
||||
int error_code;
|
||||
char tty_string[256];
|
||||
|
||||
g_assert (worker->priv->pam_handle == NULL);
|
||||
|
||||
g_debug ("GdmSessionWorker: initializing PAM; service=%s username=%s seat=%s",
|
||||
service ? service : "(null)",
|
||||
username ? username : "(null)",
|
||||
seat_id ? seat_id : "(null)");
|
||||
|
||||
#ifdef SUPPORTS_PAM_EXTENSIONS
|
||||
if (extensions != NULL) {
|
||||
GDM_PAM_EXTENSION_ADVERTISE_SUPPORTED_EXTENSIONS (gdm_pam_extension_environment_block, extensions);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1204,64 +1182,63 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
|
||||
}
|
||||
|
||||
/* set RHOST */
|
||||
if (hostname != NULL && hostname[0] != '\0') {
|
||||
error_code = pam_set_item (worker->priv->pam_handle, PAM_RHOST, hostname);
|
||||
g_debug ("error informing authentication system of user's hostname %s: %s",
|
||||
hostname,
|
||||
pam_strerror (worker->priv->pam_handle, error_code));
|
||||
|
||||
if (error_code != PAM_SUCCESS) {
|
||||
g_set_error (error,
|
||||
GDM_SESSION_WORKER_ERROR,
|
||||
GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
|
||||
"%s", "");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* set seat ID */
|
||||
if (seat_id != NULL && seat_id[0] != '\0') {
|
||||
gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
|
||||
}
|
||||
|
||||
if (strcmp (service, "gdm-launch-environment") == 0) {
|
||||
gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
|
||||
}
|
||||
|
||||
g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
|
||||
|
||||
- /* Temporarily set PAM_TTY with the currently active VT (login screen)
|
||||
+ /* Temporarily set PAM_TTY with the login VT,
|
||||
PAM_TTY will be reset with the users VT right before the user session is opened */
|
||||
- ensure_login_vt (worker);
|
||||
- g_snprintf (tty_string, 256, "/dev/tty%d", worker->priv->login_vt);
|
||||
+ g_snprintf (tty_string, 256, "/dev/tty%d", GDM_INITIAL_VT);
|
||||
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
|
||||
if (!display_is_local)
|
||||
worker->priv->password_is_required = TRUE;
|
||||
|
||||
out:
|
||||
if (error_code != PAM_SUCCESS) {
|
||||
gdm_session_worker_uninitialize_pam (worker, error_code);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
|
||||
gboolean password_is_required,
|
||||
GError **error)
|
||||
{
|
||||
int error_code;
|
||||
int authentication_flags;
|
||||
|
||||
g_debug ("GdmSessionWorker: authenticating user %s", worker->priv->username);
|
||||
|
||||
authentication_flags = 0;
|
||||
|
||||
if (password_is_required) {
|
||||
authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK;
|
||||
}
|
||||
|
||||
/* blocking call, does the actual conversation */
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,160 @@
|
||||
From 75b65846ca77bd2d42e25365b4b7242a406330cf Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 7 Apr 2020 14:37:41 -0400
|
||||
Subject: [PATCH 44/51] session-worker: ensure initial vt is never picked for
|
||||
!is_initial displays
|
||||
|
||||
Normally, a !is_initial display would never "get" tty1, since the system
|
||||
boots to tty1. But if, for some reason, the user booted to runlevel 3,
|
||||
then switched to runlevel 5, the login screen could get started when
|
||||
tty1 is free.
|
||||
|
||||
That means, e.g., an autologin user can end up getting allocated tty1,
|
||||
which is bad, since we assume tty1 is used for the login screen.
|
||||
|
||||
This commit opens up /dev/tty1 when querying for available VTs, so that
|
||||
it never gets returned by the kernel as available.
|
||||
---
|
||||
daemon/gdm-session-worker.c | 39 +++++++++++++++++++++++++------------
|
||||
1 file changed, 27 insertions(+), 12 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
|
||||
index 0bd78cfaf..42c415837 100644
|
||||
--- a/daemon/gdm-session-worker.c
|
||||
+++ b/daemon/gdm-session-worker.c
|
||||
@@ -2167,105 +2167,120 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
|
||||
|
||||
/* If we end up execing again, make sure we don't use the executable context set up
|
||||
* by pam_selinux durin pam_open_session
|
||||
*/
|
||||
#ifdef HAVE_SELINUX
|
||||
setexeccon (NULL);
|
||||
#endif
|
||||
|
||||
worker->priv->child_pid = session_pid;
|
||||
|
||||
g_debug ("GdmSessionWorker: session opened creating reply...");
|
||||
g_assert (sizeof (GPid) <= sizeof (int));
|
||||
|
||||
g_debug ("GdmSessionWorker: state SESSION_STARTED");
|
||||
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
|
||||
|
||||
gdm_session_worker_watch_child (worker);
|
||||
|
||||
out:
|
||||
if (error_code != PAM_SUCCESS) {
|
||||
gdm_session_worker_uninitialize_pam (worker, error_code);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_up_for_new_vt (GdmSessionWorker *worker)
|
||||
{
|
||||
- int fd;
|
||||
+ int initial_vt_fd;
|
||||
char vt_string[256], tty_string[256];
|
||||
int session_vt = 0;
|
||||
|
||||
- fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
-
|
||||
- if (fd < 0) {
|
||||
- g_debug ("GdmSessionWorker: couldn't open VT master: %m");
|
||||
+ /* open the initial vt. We need it for two scenarios:
|
||||
+ *
|
||||
+ * 1) display_is_initial is TRUE. We need it directly.
|
||||
+ * 2) display_is_initial is FALSE. We need it to mark
|
||||
+ * the initial VT as "in use" so it doesn't get returned
|
||||
+ * by VT_OPENQRY
|
||||
+ * */
|
||||
+ g_snprintf (tty_string, sizeof (tty_string), "/dev/tty%d", GDM_INITIAL_VT);
|
||||
+ initial_vt_fd = open (tty_string, O_RDWR | O_NOCTTY);
|
||||
+
|
||||
+ if (initial_vt_fd < 0) {
|
||||
+ g_debug ("GdmSessionWorker: couldn't open console of initial fd: %m");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (worker->priv->display_is_initial) {
|
||||
session_vt = GDM_INITIAL_VT;
|
||||
} else {
|
||||
- if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
|
||||
+
|
||||
+ /* Typically VT_OPENQRY is called on /dev/tty0, but we already
|
||||
+ * have /dev/tty1 open above, so might as well use it.
|
||||
+ */
|
||||
+ if (ioctl (initial_vt_fd, VT_OPENQRY, &session_vt) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't open new VT: %m");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
worker->priv->session_vt = session_vt;
|
||||
|
||||
- close (fd);
|
||||
- fd = -1;
|
||||
-
|
||||
g_assert (session_vt > 0);
|
||||
|
||||
g_snprintf (vt_string, sizeof (vt_string), "%d", session_vt);
|
||||
|
||||
/* Set the VTNR. This is used by logind to configure a session in
|
||||
* the logind-managed case, but it doesn't hurt to set it always.
|
||||
* When logind gains support for XDG_VTNR=auto, we can make the
|
||||
* OPENQRY and this whole path only used by the new VT code. */
|
||||
gdm_session_worker_set_environment_variable (worker,
|
||||
"XDG_VTNR",
|
||||
vt_string);
|
||||
|
||||
- g_snprintf (tty_string, 256, "/dev/tty%d", session_vt);
|
||||
- worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
|
||||
+ if (worker->priv->display_is_initial) {
|
||||
+ worker->priv->session_tty_fd = initial_vt_fd;
|
||||
+ } else {
|
||||
+ g_snprintf (tty_string, sizeof (tty_string), "/dev/tty%d", session_vt);
|
||||
+ worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
|
||||
+ close (initial_vt_fd);
|
||||
+ }
|
||||
+
|
||||
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
- close (fd);
|
||||
+ close (initial_vt_fd);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
set_xdg_vtnr_to_current_vt (GdmSessionWorker *worker)
|
||||
{
|
||||
int fd;
|
||||
char vt_string[256];
|
||||
struct vt_stat vt_state = { 0 };
|
||||
|
||||
fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
|
||||
|
||||
if (fd < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't open VT master: %m");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
|
||||
g_debug ("GdmSessionWorker: couldn't get current VT: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
g_snprintf (vt_string, sizeof (vt_string), "%d", vt_state.v_active);
|
||||
|
||||
gdm_session_worker_set_environment_variable (worker,
|
||||
"XDG_VTNR",
|
||||
vt_string);
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,114 @@
|
||||
From fc3503f16e9de535d2a36b904720b360370f880f Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 15 May 2020 10:08:24 -0400
|
||||
Subject: [PATCH 45/51] local-display-factory: Always force login screen to VT
|
||||
1
|
||||
|
||||
These days we always want the login screen on VT 1, even
|
||||
when it's created by user switching.
|
||||
|
||||
Unfortunately, since commit f843233ad the login screen
|
||||
won't naturally pick VT 1 when user switching.
|
||||
|
||||
This commit forces it to make the right choice.
|
||||
|
||||
Closes https://gitlab.gnome.org/GNOME/gdm/-/issues/602
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 3 +++
|
||||
1 file changed, 3 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index 7a013c694..a288f8765 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -197,84 +197,87 @@ store_display (GdmLocalDisplayFactory *factory,
|
||||
gdm_display_store_add (store, display);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdm_local_display_factory_use_wayland (void)
|
||||
{
|
||||
#ifdef ENABLE_WAYLAND_SUPPORT
|
||||
gboolean wayland_enabled = FALSE;
|
||||
if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
|
||||
if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
|
||||
return TRUE;
|
||||
}
|
||||
#endif
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
Example:
|
||||
dbus-send --system --dest=org.gnome.DisplayManager \
|
||||
--type=method_call --print-reply --reply-timeout=2000 \
|
||||
/org/gnome/DisplayManager/Manager \
|
||||
org.gnome.DisplayManager.Manager.GetDisplays
|
||||
*/
|
||||
gboolean
|
||||
gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
|
||||
char **id,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret;
|
||||
GdmDisplay *display = NULL;
|
||||
+ gboolean is_initial = FALSE;
|
||||
|
||||
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
|
||||
|
||||
ret = FALSE;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: Creating transient display");
|
||||
|
||||
#ifdef ENABLE_USER_DISPLAY_SERVER
|
||||
display = gdm_local_display_new ();
|
||||
if (gdm_local_display_factory_use_wayland ())
|
||||
g_object_set (G_OBJECT (display), "session-type", "wayland", NULL);
|
||||
+ is_initial = TRUE;
|
||||
#else
|
||||
if (display == NULL) {
|
||||
guint32 num;
|
||||
|
||||
num = take_next_display_number (factory);
|
||||
|
||||
display = gdm_legacy_display_new (num);
|
||||
}
|
||||
#endif
|
||||
|
||||
g_object_set (display,
|
||||
"seat-id", "seat0",
|
||||
"allow-timed-login", FALSE,
|
||||
+ "is-initial", is_initial,
|
||||
NULL);
|
||||
|
||||
store_display (factory, display);
|
||||
|
||||
if (! gdm_display_manage (display)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (! gdm_display_get_id (display, id, NULL)) {
|
||||
display = NULL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
/* ref either held by store or not at all */
|
||||
g_object_unref (display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
|
||||
GdmDisplay *display,
|
||||
const char *seat_id)
|
||||
{
|
||||
if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
|
||||
return FALSE;
|
||||
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,81 @@
|
||||
From 763e31a576a4cd665e5ad06ad0eb4610cecc0b42 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Fri, 10 Jul 2020 10:45:52 -0400
|
||||
Subject: [PATCH 46/51] gdm-x-session: tell x server to not vt switch
|
||||
|
||||
gdm already handles the VT switching on X's behalf,
|
||||
so it's redundant, and X does it at inopportune times,
|
||||
so instruct it to not get involved.
|
||||
---
|
||||
daemon/gdm-x-session.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
|
||||
index 3b2fcef47..d8e3c7d53 100644
|
||||
--- a/daemon/gdm-x-session.c
|
||||
+++ b/daemon/gdm-x-session.c
|
||||
@@ -247,60 +247,61 @@ spawn_x_server (State *state,
|
||||
}
|
||||
|
||||
g_ptr_array_add (arguments, "-displayfd");
|
||||
g_ptr_array_add (arguments, display_fd_string);
|
||||
|
||||
g_ptr_array_add (arguments, "-auth");
|
||||
g_ptr_array_add (arguments, auth_file);
|
||||
|
||||
/* If we were compiled with Xserver >= 1.17 we need to specify
|
||||
* '-listen tcp' as the X server dosen't listen on tcp sockets
|
||||
* by default anymore. In older versions we need to pass
|
||||
* -nolisten tcp to disable listening on tcp sockets.
|
||||
*/
|
||||
#ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY
|
||||
if (allow_remote_connections) {
|
||||
g_ptr_array_add (arguments, "-listen");
|
||||
g_ptr_array_add (arguments, "tcp");
|
||||
}
|
||||
#else
|
||||
if (!allow_remote_connections) {
|
||||
g_ptr_array_add (arguments, "-nolisten");
|
||||
g_ptr_array_add (arguments, "tcp");
|
||||
}
|
||||
#endif
|
||||
|
||||
g_ptr_array_add (arguments, "-background");
|
||||
g_ptr_array_add (arguments, "none");
|
||||
|
||||
g_ptr_array_add (arguments, "-noreset");
|
||||
g_ptr_array_add (arguments, "-keeptty");
|
||||
+ g_ptr_array_add (arguments, "-novtswitch");
|
||||
|
||||
g_ptr_array_add (arguments, "-verbose");
|
||||
if (state->debug_enabled) {
|
||||
g_ptr_array_add (arguments, "7");
|
||||
} else {
|
||||
g_ptr_array_add (arguments, "3");
|
||||
}
|
||||
|
||||
if (state->debug_enabled) {
|
||||
g_ptr_array_add (arguments, "-core");
|
||||
}
|
||||
g_ptr_array_add (arguments, NULL);
|
||||
|
||||
subprocess = g_subprocess_launcher_spawnv (launcher,
|
||||
(const char * const *) arguments->pdata,
|
||||
&error);
|
||||
g_free (display_fd_string);
|
||||
g_clear_object (&launcher);
|
||||
g_ptr_array_free (arguments, TRUE);
|
||||
|
||||
if (subprocess == NULL) {
|
||||
g_debug ("could not start X server: %s", error->message);
|
||||
goto out;
|
||||
}
|
||||
|
||||
input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
|
||||
data_stream = g_data_input_stream_new (input_stream);
|
||||
g_clear_object (&input_stream);
|
||||
|
||||
display_number = g_data_input_stream_read_line (data_stream,
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,115 @@
|
||||
From a1c74e2e42dea464ab0b439b767da5c12cbf3986 Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Thu, 11 Oct 2018 07:15:56 -0400
|
||||
Subject: [PATCH 47/51] local-display-factory: kill X on login just like
|
||||
wayland
|
||||
|
||||
These days we kill the wayland login screen during login to
|
||||
conserve system resources.
|
||||
|
||||
We've been reluctant to do the same for X based login screens,
|
||||
because X didn't handle being killed in the background so well.
|
||||
|
||||
This is no longer a problem, since this commit:
|
||||
|
||||
https://gitlab.freedesktop.org/xorg/xserver/-/commit/ff91c696ff8f5f56da40e107cb5c321539758a81
|
||||
|
||||
So let's go ahead and kill it now.
|
||||
---
|
||||
daemon/gdm-local-display-factory.c | 9 ---------
|
||||
1 file changed, 9 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
||||
index a288f8765..aae226750 100644
|
||||
--- a/daemon/gdm-local-display-factory.c
|
||||
+++ b/daemon/gdm-local-display-factory.c
|
||||
@@ -599,86 +599,77 @@ on_seat_removed (GDBusConnection *connection,
|
||||
|
||||
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
||||
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
||||
}
|
||||
|
||||
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
static gboolean
|
||||
lookup_by_session_id (const char *id,
|
||||
GdmDisplay *display,
|
||||
gpointer user_data)
|
||||
{
|
||||
const char *looking_for = user_data;
|
||||
const char *current;
|
||||
|
||||
current = gdm_display_get_session_id (display);
|
||||
return g_strcmp0 (current, looking_for) == 0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
finish_waiting_displays_on_seat (factory, "seat0");
|
||||
factory->priv->wait_to_finish_timeout_id = 0;
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
|
||||
GdmDisplay *display)
|
||||
{
|
||||
- g_autofree char *display_session_type = NULL;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
|
||||
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
- "session-type", &display_session_type,
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
NULL);
|
||||
|
||||
/* we don't ever stop initial-setup implicitly */
|
||||
if (doing_initial_setup) {
|
||||
g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
|
||||
return;
|
||||
}
|
||||
|
||||
- /* we can only stop greeter for wayland sessions, since
|
||||
- * X server would jump back on exit */
|
||||
- if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
||||
- g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
||||
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
|
||||
/* We stop the greeter after a timeout to avoid flicker */
|
||||
if (factory->priv->wait_to_finish_timeout_id != 0)
|
||||
g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
||||
|
||||
factory->priv->wait_to_finish_timeout_id =
|
||||
g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
|
||||
(GSourceFunc)wait_to_finish_timeout,
|
||||
factory);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_vt_changed (GIOChannel *source,
|
||||
GIOCondition condition,
|
||||
GdmLocalDisplayFactory *factory)
|
||||
{
|
||||
GIOStatus status;
|
||||
g_autofree char *tty_of_active_vt = NULL;
|
||||
g_autofree char *login_session_id = NULL;
|
||||
g_autofree char *active_session_id = NULL;
|
||||
unsigned int previous_vt, new_vt;
|
||||
const char *session_type = NULL;
|
||||
int ret, n_returned;
|
||||
|
||||
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
||||
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
||||
|
||||
if (condition & G_IO_PRI) {
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,149 @@
|
||||
From f1b7d85b46dfc253176d6a043dcce26da3a26dfb Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Mon, 13 Jul 2020 09:23:06 -0400
|
||||
Subject: [PATCH 48/51] manager: don't kill initial-setup right away with Xorg
|
||||
either
|
||||
|
||||
The login screen for both Xorg and wayland sessions is now silently
|
||||
killed in the background post login.
|
||||
|
||||
We still kill initial-setup for Xorg sessions up front, though.
|
||||
|
||||
This commit fixes that.
|
||||
---
|
||||
daemon/gdm-manager.c | 20 ++------------------
|
||||
1 file changed, 2 insertions(+), 18 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index cf982870c..b147d73db 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -1757,123 +1757,107 @@ chown_initial_setup_home_dir (void)
|
||||
|
||||
uid = (uid_t) atoi (gis_uid_contents);
|
||||
pwe = getpwuid (uid);
|
||||
if (uid == 0 || pwe == NULL) {
|
||||
g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = NULL;
|
||||
dir = g_file_new_for_path (gis_dir_path);
|
||||
if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
|
||||
g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
g_object_unref (dir);
|
||||
out:
|
||||
g_free (gis_uid_contents);
|
||||
g_free (gis_uid_path);
|
||||
g_free (gis_dir_path);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_start_user_session (StartUserSessionOperation *operation)
|
||||
{
|
||||
GdmManager *self = operation->manager;
|
||||
gboolean migrated;
|
||||
gboolean fail_if_already_switched = TRUE;
|
||||
gboolean doing_initial_setup = FALSE;
|
||||
GdmDisplay *display;
|
||||
const char *session_id;
|
||||
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
- g_autofree char *display_session_type = NULL;
|
||||
-#endif
|
||||
|
||||
g_debug ("GdmManager: start or jump to session");
|
||||
|
||||
/* If there's already a session running, jump to it.
|
||||
* If the only session running is the one we just opened,
|
||||
* start a session on it.
|
||||
*/
|
||||
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
|
||||
|
||||
g_debug ("GdmManager: migrated: %d", migrated);
|
||||
if (migrated) {
|
||||
/* We don't stop the manager here because
|
||||
when Xorg exits it switches to the VT it was
|
||||
started from. That interferes with fast
|
||||
user switching. */
|
||||
gdm_session_reset (operation->session);
|
||||
destroy_start_user_session_operation (operation);
|
||||
goto out;
|
||||
}
|
||||
|
||||
display = get_display_for_user_session (operation->session);
|
||||
|
||||
g_object_get (G_OBJECT (display),
|
||||
"doing-initial-setup", &doing_initial_setup,
|
||||
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
- "session-type", &display_session_type,
|
||||
-#endif
|
||||
NULL);
|
||||
|
||||
session_id = gdm_session_get_conversation_session_id (operation->session,
|
||||
operation->service_name);
|
||||
|
||||
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
|
||||
/* In this case, the greeter's display is morphing into
|
||||
* the user session display. Kill the greeter on this session
|
||||
* and let the user session follow the same display. */
|
||||
gdm_display_stop_greeter_session (display);
|
||||
g_object_set (G_OBJECT (display),
|
||||
"session-class", "user",
|
||||
"session-id", session_id,
|
||||
NULL);
|
||||
} else {
|
||||
uid_t allowed_uid;
|
||||
|
||||
g_object_ref (display);
|
||||
if (doing_initial_setup) {
|
||||
g_autoptr(GError) error = NULL;
|
||||
|
||||
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
||||
- if (g_strcmp0 (display_session_type, "wayland") == 0) {
|
||||
- g_debug ("GdmManager: closing down initial setup display in background");
|
||||
- g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
- }
|
||||
-#endif
|
||||
- if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
|
||||
- g_debug ("GdmManager: closing down initial setup display");
|
||||
- gdm_display_stop_greeter_session (display);
|
||||
- gdm_display_unmanage (display);
|
||||
- gdm_display_finish (display);
|
||||
- }
|
||||
+ g_debug ("GdmManager: closing down initial setup display in background");
|
||||
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
||||
|
||||
chown_initial_setup_home_dir ();
|
||||
|
||||
if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
|
||||
"1",
|
||||
1,
|
||||
&error)) {
|
||||
g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
|
||||
ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
|
||||
error->message);
|
||||
g_clear_error (&error);
|
||||
}
|
||||
} else {
|
||||
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
|
||||
}
|
||||
|
||||
/* The user session is going to follow the session worker
|
||||
* into the new display. Untie it from this display and
|
||||
* create a new session for a future user login. */
|
||||
allowed_uid = gdm_session_get_allowed_user (operation->session);
|
||||
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
|
||||
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
|
||||
create_user_session_for_display (operation->manager, display, allowed_uid);
|
||||
|
||||
/* Give the user session a new display object for bookkeeping purposes */
|
||||
create_display_for_user_session (operation->manager,
|
||||
operation->session,
|
||||
session_id);
|
||||
|
||||
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
|
||||
--
|
||||
2.27.0
|
||||
|
@ -0,0 +1,551 @@
|
||||
From 2724b4fd6d4ac527acc481f056f535141b63fe24 Mon Sep 17 00:00:00 2001
|
||||
From: Iain Lane <iainl@gnome.org>
|
||||
Date: Tue, 7 May 2019 15:57:43 +0100
|
||||
Subject: [PATCH 49/51] GdmManager, GdmDisplay: Add RegisterSession method
|
||||
|
||||
Window managers can use this to register with GDM when they've finished
|
||||
starting up and started displaying.
|
||||
---
|
||||
daemon/gdm-display.c | 24 ++++++++++++++++++++++++
|
||||
daemon/gdm-manager.c | 30 ++++++++++++++++++++++++++++++
|
||||
daemon/gdm-manager.xml | 3 +++
|
||||
3 files changed, 57 insertions(+)
|
||||
|
||||
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
|
||||
index 1cef8c7c1..56799741d 100644
|
||||
--- a/daemon/gdm-display.c
|
||||
+++ b/daemon/gdm-display.c
|
||||
@@ -64,82 +64,84 @@ struct GdmDisplayPrivate
|
||||
char *remote_hostname;
|
||||
int x11_display_number;
|
||||
char *x11_display_name;
|
||||
int status;
|
||||
time_t creation_time;
|
||||
GTimer *server_timer;
|
||||
|
||||
char *x11_cookie;
|
||||
gsize x11_cookie_size;
|
||||
GdmDisplayAccessFile *access_file;
|
||||
|
||||
guint finish_idle_id;
|
||||
|
||||
xcb_connection_t *xcb_connection;
|
||||
int xcb_screen_number;
|
||||
|
||||
GDBusConnection *connection;
|
||||
GdmDisplayAccessFile *user_access_file;
|
||||
|
||||
GdmDBusDisplay *display_skeleton;
|
||||
GDBusObjectSkeleton *object_skeleton;
|
||||
|
||||
/* this spawns and controls the greeter session */
|
||||
GdmLaunchEnvironment *launch_environment;
|
||||
|
||||
guint is_local : 1;
|
||||
guint is_initial : 1;
|
||||
guint allow_timed_login : 1;
|
||||
guint have_existing_user_accounts : 1;
|
||||
guint doing_initial_setup : 1;
|
||||
+ guint session_registered : 1;
|
||||
};
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_ID,
|
||||
PROP_STATUS,
|
||||
PROP_SEAT_ID,
|
||||
PROP_SESSION_ID,
|
||||
PROP_SESSION_CLASS,
|
||||
PROP_SESSION_TYPE,
|
||||
PROP_REMOTE_HOSTNAME,
|
||||
PROP_X11_DISPLAY_NUMBER,
|
||||
PROP_X11_DISPLAY_NAME,
|
||||
PROP_X11_COOKIE,
|
||||
PROP_X11_AUTHORITY_FILE,
|
||||
PROP_IS_CONNECTED,
|
||||
PROP_IS_LOCAL,
|
||||
PROP_LAUNCH_ENVIRONMENT,
|
||||
PROP_IS_INITIAL,
|
||||
PROP_ALLOW_TIMED_LOGIN,
|
||||
PROP_HAVE_EXISTING_USER_ACCOUNTS,
|
||||
PROP_DOING_INITIAL_SETUP,
|
||||
+ PROP_SESSION_REGISTERED,
|
||||
};
|
||||
|
||||
static void gdm_display_class_init (GdmDisplayClass *klass);
|
||||
static void gdm_display_init (GdmDisplay *self);
|
||||
static void gdm_display_finalize (GObject *object);
|
||||
static void queue_finish (GdmDisplay *self);
|
||||
static void _gdm_display_set_status (GdmDisplay *self,
|
||||
int status);
|
||||
static gboolean wants_initial_setup (GdmDisplay *self);
|
||||
G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
|
||||
|
||||
GQuark
|
||||
gdm_display_error_quark (void)
|
||||
{
|
||||
static GQuark ret = 0;
|
||||
if (ret == 0) {
|
||||
ret = g_quark_from_static_string ("gdm_display_error");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
time_t
|
||||
gdm_display_get_creation_time (GdmDisplay *self)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
|
||||
|
||||
return self->priv->creation_time;
|
||||
}
|
||||
|
||||
@@ -733,60 +735,68 @@ static void
|
||||
_gdm_display_set_x11_display_number (GdmDisplay *self,
|
||||
int num)
|
||||
{
|
||||
self->priv->x11_display_number = num;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdm_display_set_x11_display_name (GdmDisplay *self,
|
||||
const char *x11_display)
|
||||
{
|
||||
g_free (self->priv->x11_display_name);
|
||||
self->priv->x11_display_name = g_strdup (x11_display);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdm_display_set_x11_cookie (GdmDisplay *self,
|
||||
const char *x11_cookie)
|
||||
{
|
||||
g_free (self->priv->x11_cookie);
|
||||
self->priv->x11_cookie = g_strdup (x11_cookie);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdm_display_set_is_local (GdmDisplay *self,
|
||||
gboolean is_local)
|
||||
{
|
||||
g_debug ("GdmDisplay: local: %s", is_local? "yes" : "no");
|
||||
self->priv->is_local = is_local;
|
||||
}
|
||||
|
||||
+static void
|
||||
+_gdm_display_set_session_registered (GdmDisplay *self,
|
||||
+ gboolean registered)
|
||||
+{
|
||||
+ g_debug ("GdmDisplay: session registered: %s", registered? "yes" : "no");
|
||||
+ self->priv->session_registered = registered;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
_gdm_display_set_launch_environment (GdmDisplay *self,
|
||||
GdmLaunchEnvironment *launch_environment)
|
||||
{
|
||||
g_clear_object (&self->priv->launch_environment);
|
||||
|
||||
self->priv->launch_environment = g_object_ref (launch_environment);
|
||||
}
|
||||
|
||||
static void
|
||||
_gdm_display_set_is_initial (GdmDisplay *self,
|
||||
gboolean initial)
|
||||
{
|
||||
g_debug ("GdmDisplay: initial: %s", initial? "yes" : "no");
|
||||
self->priv->is_initial = initial;
|
||||
}
|
||||
|
||||
static void
|
||||
_gdm_display_set_allow_timed_login (GdmDisplay *self,
|
||||
gboolean allow_timed_login)
|
||||
{
|
||||
g_debug ("GdmDisplay: allow timed login: %s", allow_timed_login? "yes" : "no");
|
||||
self->priv->allow_timed_login = allow_timed_login;
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_display_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
@@ -811,60 +821,63 @@ gdm_display_set_property (GObject *object,
|
||||
case PROP_SESSION_CLASS:
|
||||
_gdm_display_set_session_class (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_SESSION_TYPE:
|
||||
_gdm_display_set_session_type (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_REMOTE_HOSTNAME:
|
||||
_gdm_display_set_remote_hostname (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_X11_DISPLAY_NUMBER:
|
||||
_gdm_display_set_x11_display_number (self, g_value_get_int (value));
|
||||
break;
|
||||
case PROP_X11_DISPLAY_NAME:
|
||||
_gdm_display_set_x11_display_name (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_X11_COOKIE:
|
||||
_gdm_display_set_x11_cookie (self, g_value_get_string (value));
|
||||
break;
|
||||
case PROP_IS_LOCAL:
|
||||
_gdm_display_set_is_local (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_ALLOW_TIMED_LOGIN:
|
||||
_gdm_display_set_allow_timed_login (self, g_value_get_boolean (value));
|
||||
break;
|
||||
case PROP_LAUNCH_ENVIRONMENT:
|
||||
_gdm_display_set_launch_environment (self, g_value_get_object (value));
|
||||
break;
|
||||
case PROP_IS_INITIAL:
|
||||
_gdm_display_set_is_initial (self, g_value_get_boolean (value));
|
||||
break;
|
||||
+ case PROP_SESSION_REGISTERED:
|
||||
+ _gdm_display_set_session_registered (self, g_value_get_boolean (value));
|
||||
+ break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_display_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdmDisplay *self;
|
||||
|
||||
self = GDM_DISPLAY (object);
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_ID:
|
||||
g_value_set_string (value, self->priv->id);
|
||||
break;
|
||||
case PROP_STATUS:
|
||||
g_value_set_int (value, self->priv->status);
|
||||
break;
|
||||
case PROP_SEAT_ID:
|
||||
g_value_set_string (value, self->priv->seat_id);
|
||||
break;
|
||||
case PROP_SESSION_ID:
|
||||
g_value_set_string (value, self->priv->session_id);
|
||||
break;
|
||||
case PROP_SESSION_CLASS:
|
||||
@@ -881,60 +894,63 @@ gdm_display_get_property (GObject *object,
|
||||
break;
|
||||
case PROP_X11_DISPLAY_NAME:
|
||||
g_value_set_string (value, self->priv->x11_display_name);
|
||||
break;
|
||||
case PROP_X11_COOKIE:
|
||||
g_value_set_string (value, self->priv->x11_cookie);
|
||||
break;
|
||||
case PROP_X11_AUTHORITY_FILE:
|
||||
g_value_take_string (value,
|
||||
self->priv->access_file?
|
||||
gdm_display_access_file_get_path (self->priv->access_file) : NULL);
|
||||
break;
|
||||
case PROP_IS_LOCAL:
|
||||
g_value_set_boolean (value, self->priv->is_local);
|
||||
break;
|
||||
case PROP_IS_CONNECTED:
|
||||
g_value_set_boolean (value, self->priv->xcb_connection != NULL);
|
||||
break;
|
||||
case PROP_LAUNCH_ENVIRONMENT:
|
||||
g_value_set_object (value, self->priv->launch_environment);
|
||||
break;
|
||||
case PROP_IS_INITIAL:
|
||||
g_value_set_boolean (value, self->priv->is_initial);
|
||||
break;
|
||||
case PROP_HAVE_EXISTING_USER_ACCOUNTS:
|
||||
g_value_set_boolean (value, self->priv->have_existing_user_accounts);
|
||||
break;
|
||||
case PROP_DOING_INITIAL_SETUP:
|
||||
g_value_set_boolean (value, self->priv->doing_initial_setup);
|
||||
break;
|
||||
+ case PROP_SESSION_REGISTERED:
|
||||
+ g_value_set_boolean (value, priv->session_registered);
|
||||
+ break;
|
||||
case PROP_ALLOW_TIMED_LOGIN:
|
||||
g_value_set_boolean (value, self->priv->allow_timed_login);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_get_id (GdmDBusDisplay *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
char *id;
|
||||
|
||||
gdm_display_get_id (self, &id, NULL);
|
||||
|
||||
gdm_dbus_display_complete_get_id (skeleton, invocation, id);
|
||||
|
||||
g_free (id);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_get_remote_hostname (GdmDBusDisplay *skeleton,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
char *hostname;
|
||||
@@ -1197,60 +1213,68 @@ gdm_display_class_init (GdmDisplayClass *klass)
|
||||
G_PARAM_READABLE));
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_IS_LOCAL,
|
||||
g_param_spec_boolean ("is-local",
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_IS_CONNECTED,
|
||||
g_param_spec_boolean ("is-connected",
|
||||
NULL,
|
||||
NULL,
|
||||
TRUE,
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_HAVE_EXISTING_USER_ACCOUNTS,
|
||||
g_param_spec_boolean ("have-existing-user-accounts",
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_DOING_INITIAL_SETUP,
|
||||
g_param_spec_boolean ("doing-initial-setup",
|
||||
NULL,
|
||||
NULL,
|
||||
FALSE,
|
||||
G_PARAM_READABLE));
|
||||
+ g_object_class_install_property (object_class,
|
||||
+ PROP_SESSION_REGISTERED,
|
||||
+ g_param_spec_boolean ("session-registered",
|
||||
+ NULL,
|
||||
+ NULL,
|
||||
+ FALSE,
|
||||
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
+
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_LAUNCH_ENVIRONMENT,
|
||||
g_param_spec_object ("launch-environment",
|
||||
NULL,
|
||||
NULL,
|
||||
GDM_TYPE_LAUNCH_ENVIRONMENT,
|
||||
G_PARAM_READWRITE));
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_STATUS,
|
||||
g_param_spec_int ("status",
|
||||
"status",
|
||||
"status",
|
||||
-1,
|
||||
G_MAXINT,
|
||||
GDM_DISPLAY_UNMANAGED,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
|
||||
|
||||
g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
gdm_display_init (GdmDisplay *self)
|
||||
{
|
||||
|
||||
self->priv = GDM_DISPLAY_GET_PRIVATE (self);
|
||||
|
||||
self->priv->creation_time = time (NULL);
|
||||
self->priv->server_timer = g_timer_new ();
|
||||
}
|
||||
|
||||
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
|
||||
index b147d73db..bff602a07 100644
|
||||
--- a/daemon/gdm-manager.c
|
||||
+++ b/daemon/gdm-manager.c
|
||||
@@ -789,60 +789,89 @@ gdm_manager_handle_register_display (GdmDBusManager *manager,
|
||||
if (session != NULL) {
|
||||
GPid pid;
|
||||
|
||||
if (x11_display_name != NULL) {
|
||||
g_object_set (G_OBJECT (session), "display-name", x11_display_name, NULL);
|
||||
g_object_set (G_OBJECT (display), "x11-display-name", x11_display_name, NULL);
|
||||
}
|
||||
|
||||
/* FIXME: this should happen in gdm-session.c when the session is opened
|
||||
*/
|
||||
if (tty != NULL)
|
||||
g_object_set (G_OBJECT (session), "display-device", tty, NULL);
|
||||
|
||||
pid = gdm_session_get_pid (session);
|
||||
|
||||
if (pid > 0) {
|
||||
add_session_record (self, session, pid, SESSION_RECORD_LOGIN);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL);
|
||||
|
||||
gdm_dbus_manager_complete_register_display (GDM_DBUS_MANAGER (manager),
|
||||
invocation);
|
||||
|
||||
g_clear_pointer (&x11_display_name, g_free);
|
||||
g_clear_pointer (&tty, g_free);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
+static gboolean
|
||||
+gdm_manager_handle_register_session (GdmDBusManager *manager,
|
||||
+ GDBusMethodInvocation *invocation,
|
||||
+ GVariant *details)
|
||||
+{
|
||||
+ GdmManager *self = GDM_MANAGER (manager);
|
||||
+ GdmDisplay *display;
|
||||
+ const char *sender;
|
||||
+ GDBusConnection *connection;
|
||||
+
|
||||
+ sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
+ connection = g_dbus_method_invocation_get_connection (invocation);
|
||||
+
|
||||
+ get_display_and_details_for_bus_sender (self, connection, sender, &display,
|
||||
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
+
|
||||
+ g_debug ("GdmManager: trying to register new session on display %p", display);
|
||||
+
|
||||
+ if (display != NULL)
|
||||
+ g_object_set (G_OBJECT (display), "session-registered", TRUE, NULL);
|
||||
+ else
|
||||
+ g_debug ("GdmManager: No display, not registering");
|
||||
+
|
||||
+ gdm_dbus_manager_complete_register_session (GDM_DBUS_MANAGER (manager),
|
||||
+ invocation);
|
||||
+
|
||||
+ return TRUE;
|
||||
+}
|
||||
+
|
||||
static gboolean
|
||||
gdm_manager_handle_open_session (GdmDBusManager *manager,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
GdmManager *self = GDM_MANAGER (manager);
|
||||
const char *sender;
|
||||
GDBusConnection *connection;
|
||||
GdmDisplay *display = NULL;
|
||||
GdmSession *session = NULL;
|
||||
const char *address;
|
||||
GPid pid = 0;
|
||||
uid_t uid = (uid_t) -1;
|
||||
uid_t allowed_user;
|
||||
|
||||
g_debug ("GdmManager: trying to open new session");
|
||||
|
||||
sender = g_dbus_method_invocation_get_sender (invocation);
|
||||
connection = g_dbus_method_invocation_get_connection (invocation);
|
||||
get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, NULL, &pid, &uid, NULL, NULL);
|
||||
|
||||
if (display == NULL) {
|
||||
g_dbus_method_invocation_return_error_literal (invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_ACCESS_DENIED,
|
||||
_("No session available"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#ifdef HAVE_LIBXDMCP
|
||||
@@ -1167,60 +1196,61 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager
|
||||
g_hash_table_insert (self->priv->open_reauthentication_requests,
|
||||
GINT_TO_POINTER (pid),
|
||||
invocation);
|
||||
} else if (is_login_screen) {
|
||||
g_dbus_method_invocation_return_error_literal (invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_ACCESS_DENIED,
|
||||
"Login screen only allowed to open reauthentication channels for running sessions");
|
||||
return TRUE;
|
||||
} else {
|
||||
char *address;
|
||||
address = open_temporary_reauthentication_channel (self,
|
||||
seat_id,
|
||||
session_id,
|
||||
pid,
|
||||
uid,
|
||||
is_remote);
|
||||
gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
|
||||
invocation,
|
||||
address);
|
||||
g_free (address);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
manager_interface_init (GdmDBusManagerIface *interface)
|
||||
{
|
||||
interface->handle_register_display = gdm_manager_handle_register_display;
|
||||
+ interface->handle_register_session = gdm_manager_handle_register_session;
|
||||
interface->handle_open_session = gdm_manager_handle_open_session;
|
||||
interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
display_is_on_seat0 (GdmDisplay *display)
|
||||
{
|
||||
gboolean is_on_seat0 = TRUE;
|
||||
char *seat_id = NULL;
|
||||
|
||||
g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
|
||||
|
||||
if (g_strcmp0 (seat_id, "seat0") != 0) {
|
||||
is_on_seat0 = FALSE;
|
||||
}
|
||||
|
||||
g_free (seat_id);
|
||||
|
||||
return is_on_seat0;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
get_timed_login_details (GdmManager *manager,
|
||||
char **usernamep,
|
||||
int *delayp)
|
||||
{
|
||||
gboolean res;
|
||||
gboolean enabled;
|
||||
|
||||
int delay;
|
||||
diff --git a/daemon/gdm-manager.xml b/daemon/gdm-manager.xml
|
||||
index f11f3fb73..92ef1d02d 100644
|
||||
--- a/daemon/gdm-manager.xml
|
||||
+++ b/daemon/gdm-manager.xml
|
||||
@@ -1,16 +1,19 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node name="/org/gnome/DisplayManager/Manager">
|
||||
<interface name="org.gnome.DisplayManager.Manager">
|
||||
<method name="RegisterDisplay">
|
||||
<arg name="details" direction="in" type="a{ss}"/>
|
||||
</method>
|
||||
+ <method name="RegisterSession">
|
||||
+ <arg name="details" direction="in" type="a{sv}"/>
|
||||
+ </method>
|
||||
<method name="OpenSession">
|
||||
<arg name="address" direction="out" type="s"/>
|
||||
</method>
|
||||
<method name="OpenReauthenticationChannel">
|
||||
<arg name="username" direction="in" type="s"/>
|
||||
<arg name="address" direction="out" type="s"/>
|
||||
</method>
|
||||
<property name="Version" type="s" access="read"/>
|
||||
</interface>
|
||||
</node>
|
||||
--
|
||||
2.28.0
|
||||
|
1917
SOURCES/0050-Allow-sessions-to-register-with-GDM.patch
Normal file
1917
SOURCES/0050-Allow-sessions-to-register-with-GDM.patch
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,173 @@
|
||||
From f6a8a36717afc7ce00bdb2305a6219c28abc36fb Mon Sep 17 00:00:00 2001
|
||||
From: Ray Strode <rstrode@redhat.com>
|
||||
Date: Tue, 1 Sep 2020 13:49:27 -0400
|
||||
Subject: [PATCH 51/51] display: Handle failure before display registration
|
||||
|
||||
Normally, e.g., gdm-wayland-session would register its display
|
||||
before starting the session. This display registration is how
|
||||
the display moves to the "managed" state. We currently detect
|
||||
session failure in gdm_display_unmanage. If gdm-wayland-session
|
||||
is killed before it registers the display, gdm_display_unmanage
|
||||
won't run, and failure won't be detected.
|
||||
|
||||
This commit make gdm_display_unmanage get called, even if the
|
||||
display isn't yet fully managed.
|
||||
---
|
||||
daemon/gdm-display.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
|
||||
index ae20491cd..b8ccbbd72 100644
|
||||
--- a/daemon/gdm-display.c
|
||||
+++ b/daemon/gdm-display.c
|
||||
@@ -575,80 +575,79 @@ gdm_display_disconnect (GdmDisplay *self)
|
||||
return;
|
||||
}
|
||||
|
||||
setup = xcb_get_setup (self->priv->xcb_connection);
|
||||
|
||||
/* resource_id_mask is the bits given to each client for
|
||||
* addressing resources */
|
||||
highest_client = (XID) ~unused_bits & ~setup->resource_id_mask;
|
||||
client_increment = setup->resource_id_mask + 1;
|
||||
|
||||
/* Kill every client but ourselves, then close our own connection
|
||||
*/
|
||||
for (client = 0;
|
||||
client <= highest_client;
|
||||
client += client_increment) {
|
||||
|
||||
if (client != setup->resource_id_base)
|
||||
xcb_kill_client (self->priv->xcb_connection, client);
|
||||
}
|
||||
|
||||
xcb_flush (self->priv->xcb_connection);
|
||||
|
||||
g_clear_pointer (&self->priv->xcb_connection, xcb_disconnect);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_display_unmanage (GdmDisplay *self)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
||||
|
||||
- g_debug ("GdmDisplay: unmanage display");
|
||||
-
|
||||
gdm_display_disconnect (self);
|
||||
|
||||
if (self->priv->user_access_file != NULL) {
|
||||
gdm_display_access_file_close (self->priv->user_access_file);
|
||||
g_object_unref (self->priv->user_access_file);
|
||||
self->priv->user_access_file = NULL;
|
||||
}
|
||||
|
||||
if (self->priv->access_file != NULL) {
|
||||
gdm_display_access_file_close (self->priv->access_file);
|
||||
g_object_unref (self->priv->access_file);
|
||||
self->priv->access_file = NULL;
|
||||
}
|
||||
|
||||
if (!self->priv->session_registered) {
|
||||
g_warning ("GdmDisplay: Session never registered, failing");
|
||||
_gdm_display_set_status (self, GDM_DISPLAY_FAILED);
|
||||
} else {
|
||||
+ g_debug ("GdmDisplay: Unmanage display");
|
||||
_gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_display_get_id (GdmDisplay *self,
|
||||
char **id,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
||||
|
||||
if (id != NULL) {
|
||||
*id = g_strdup (self->priv->id);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
gdm_display_get_x11_display_name (GdmDisplay *self,
|
||||
char **x11_display,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
|
||||
|
||||
if (x11_display != NULL) {
|
||||
*x11_display = g_strdup (self->priv->x11_display_name);
|
||||
}
|
||||
@@ -1309,63 +1308,62 @@ gdm_display_finalize (GObject *object)
|
||||
|
||||
GDBusObjectSkeleton *
|
||||
gdm_display_get_object_skeleton (GdmDisplay *self)
|
||||
{
|
||||
return self->priv->object_skeleton;
|
||||
}
|
||||
|
||||
static void
|
||||
on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
char *session_id;
|
||||
|
||||
g_debug ("GdmDisplay: Greeter session opened");
|
||||
session_id = gdm_launch_environment_get_session_id (launch_environment);
|
||||
_gdm_display_set_session_id (self, session_id);
|
||||
g_free (session_id);
|
||||
}
|
||||
|
||||
static void
|
||||
on_launch_environment_session_started (GdmLaunchEnvironment *launch_environment,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
g_debug ("GdmDisplay: Greeter started");
|
||||
}
|
||||
|
||||
static void
|
||||
self_destruct (GdmDisplay *self)
|
||||
{
|
||||
g_object_ref (self);
|
||||
- if (gdm_display_get_status (self) == GDM_DISPLAY_MANAGED) {
|
||||
- gdm_display_unmanage (self);
|
||||
- }
|
||||
+ g_debug ("GdmDisplay: initiating display self-destruct");
|
||||
+ gdm_display_unmanage (self);
|
||||
|
||||
if (gdm_display_get_status (self) != GDM_DISPLAY_FINISHED) {
|
||||
queue_finish (self);
|
||||
}
|
||||
g_object_unref (self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_launch_environment_session_stopped (GdmLaunchEnvironment *launch_environment,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
g_debug ("GdmDisplay: Greeter stopped");
|
||||
self_destruct (self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_launch_environment_session_exited (GdmLaunchEnvironment *launch_environment,
|
||||
int code,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
g_debug ("GdmDisplay: Greeter exited: %d", code);
|
||||
self_destruct (self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_launch_environment_session_died (GdmLaunchEnvironment *launch_environment,
|
||||
int signal,
|
||||
GdmDisplay *self)
|
||||
{
|
||||
g_debug ("GdmDisplay: Greeter died: %d", signal);
|
||||
--
|
||||
2.27.0
|
||||
|
109
SPECS/gdm.spec
109
SPECS/gdm.spec
@ -10,7 +10,7 @@
|
||||
Name: gdm
|
||||
Epoch: 1
|
||||
Version: 3.28.3
|
||||
Release: 29%{?dist}
|
||||
Release: 39%{?dist}
|
||||
Summary: The GNOME Display Manager
|
||||
|
||||
License: GPLv2+
|
||||
@ -30,8 +30,6 @@ Patch30004: 0001-data-only-disable-wayland-on-passthrough-virt-setups.patch
|
||||
|
||||
Patch40001: 0001-local-display-factory-pause-for-a-few-seconds-before.patch
|
||||
|
||||
Patch50001: 0001-manager-ensure-is-initial-is-transfered-to-autologin.patch
|
||||
|
||||
Patch60001: 0001-session-ensure-login-screen-over-XDMCP-connects-to-i.patch
|
||||
|
||||
Patch70001: 0001-worker-don-t-load-user-settings-for-program-sessions.patch
|
||||
@ -57,7 +55,72 @@ Patch110001: 0001-display-ask-accountservice-if-there-are-users-rather.patch
|
||||
|
||||
Patch120001: 0001-daemon-fix-wayland-detection-when-deciding-to-bypass.patch
|
||||
|
||||
Patch999999: system-dconf.patch
|
||||
# This truckload of patches reworks how VT allocation is done, and makes sure
|
||||
# the login screen is killed after login
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=1618481
|
||||
Patch200001: 0001-display-factory-avoid-removing-a-display-from-store-.patch
|
||||
Patch200002: 0002-local-display-factory-Add-gdm_local_display_factory_.patch
|
||||
Patch200003: 0003-local-display-factory-Use-correct-session-type-for-n.patch
|
||||
Patch200004: 0004-manager-make-get_login_window_session_id-fail-if-no-.patch
|
||||
Patch200005: 0005-manager-avoid-leaking-session_id.patch
|
||||
Patch200006: 0006-manager-gracefully-handle-the-case-of-no-session-for.patch
|
||||
Patch200007: 0007-common-dedupe-gdm_get_login_window_session_id.patch
|
||||
Patch200008: 0008-common-dedupe-activate_session_id.patch
|
||||
Patch200009: 0009-manager-plug-leak-in-maybe_activate_other_session.patch
|
||||
Patch200010: 0010-manager-start-login-screen-if-old-one-is-finished.patch
|
||||
Patch200011: 0011-manager-don-t-bail-if-session-disappears-out-from-un.patch
|
||||
Patch200012: 0012-daemon-try-harder-to-get-to-a-login-screen-at-logout.patch
|
||||
Patch200013: 0013-local-display-factory-ensure-non-seat0-codepath-does.patch
|
||||
Patch200014: 0014-daemon-kill-and-restart-greeter-on-demand-under-wayl.patch
|
||||
Patch200015: 0015-local-display-factory-add-more-debug-messages-to-new.patch
|
||||
Patch200016: 0016-local-display-factory-don-t-start-two-greeters-at-st.patch
|
||||
Patch200017: 0017-session-worker-don-t-switch-VTs-if-we-re-already-on-.patch
|
||||
Patch200018: 0018-session-worker-fix-current-vt-detection-short-circui.patch
|
||||
Patch200019: 0019-local-display-factory-don-t-jump-to-failed-display.patch
|
||||
Patch200020: 0020-local-display-factory-add-some-more-debug-statements.patch
|
||||
Patch200021: 0021-local-display-factory-ignore-spurios-SeatNew-signal-.patch
|
||||
Patch200022: 0022-common-remove-unnecessary-free.patch
|
||||
Patch200023: 0023-common-don-t-bail-if-session-disappears-out-from-und.patch
|
||||
Patch200024: 0024-manager-better-logind-handling.patch
|
||||
Patch200025: 0025-session-worker-clear-VT-before-jumping-to-it.patch
|
||||
Patch200026: 0026-manager-don-t-set-ran_once-after-running-initial-set.patch
|
||||
Patch200027: 0027-manager-start-initial-setup-right-away.patch
|
||||
Patch200028: 0028-gdm-wayland-session-gdm-x-session-register-after-del.patch
|
||||
Patch200029: 0029-local-display-factory-defer-killing-greeter-until-ne.patch
|
||||
Patch200030: 0030-daemon-Move-the-waiting-the-session-to-have-taken-ov.patch
|
||||
Patch200031: 0031-local-display-factory-don-t-autoreap-initial-setup.patch
|
||||
Patch200032: 0032-manager-rework-how-autologin-is-figured-out.patch
|
||||
Patch200033: 0033-manager-correct-display-confusion.patch
|
||||
Patch200034: 0034-manager-don-t-run-autologin-display-on-tty1.patch
|
||||
Patch200035: 0035-local-display-factory-Remove-initial-VT-is-in-use-ch.patch
|
||||
Patch200036: 0036-local-display-factory-Remove-same-VT-so-don-t-switch.patch
|
||||
Patch200037: 0037-local-display-factory-handle-reviving-displays-that-.patch
|
||||
Patch200038: 0038-manager-don-t-kill-initial-setup-before-starting-use.patch
|
||||
Patch200039: 0039-manager-do-initial-setup-post-work-in-manager-code.patch
|
||||
Patch200040: 0040-display-store-make-foreach-ignore-callback-return-va.patch
|
||||
Patch200041: 0041-xdmcp-display-factory-don-t-return-value-from-foreac.patch
|
||||
Patch200042: 0042-GdmLocalDisplayFactory-Store-VT-number-not-tty-ident.patch
|
||||
Patch200043: 0043-gdm-session-worker-Drop-login_vt-assuming-it-is-GDM_.patch
|
||||
Patch200044: 0044-session-worker-ensure-initial-vt-is-never-picked-for.patch
|
||||
Patch200045: 0045-local-display-factory-Always-force-login-screen-to-V.patch
|
||||
Patch200046: 0046-gdm-x-session-tell-x-server-to-not-vt-switch.patch
|
||||
Patch200047: 0047-local-display-factory-kill-X-on-login-just-like-wayl.patch
|
||||
Patch200048: 0048-manager-don-t-kill-initial-setup-right-away-with-Xor.patch
|
||||
Patch200049: 0049-GdmManager-GdmDisplay-Add-RegisterSession-method.patch
|
||||
Patch200050: 0050-Allow-sessions-to-register-with-GDM.patch
|
||||
Patch200051: 0051-display-Handle-failure-before-display-registration.patch
|
||||
|
||||
# CVE-2020-16125
|
||||
Patch210001: 0001-display-Exit-with-failure-if-loading-existing-users-.patch
|
||||
|
||||
# CVE-2020-27837
|
||||
Patch220001: 0001-session-worker-Don-t-switch-back-VTs-until-session-i.patch
|
||||
|
||||
Patch300001: 0001-manager-Don-t-leak-session-objects.patch
|
||||
Patch300002: 0002-session-Don-t-leak-remote-greeter-interface.patch
|
||||
Patch300003: 0003-xdmcp-display-factory-Clear-launch-environment-when-.patch
|
||||
|
||||
Patch900001: 0001-data-add-system-dconf-databases-to-gdm-profile.patch
|
||||
|
||||
BuildRequires: pam-devel >= 0:%{pam_version}
|
||||
BuildRequires: desktop-file-utils >= %{desktop_file_utils_version}
|
||||
@ -116,6 +179,7 @@ Requires: system-logos
|
||||
Requires: xorg-x11-server-utils
|
||||
Requires: xorg-x11-xinit
|
||||
Recommends: xorg-x11-server-Xorg
|
||||
Conflicts: xorg-x11-server-Xorg < 1.20.8-4
|
||||
|
||||
Obsoletes: gdm-libs < 1:3.12.0-3
|
||||
Provides: gdm-libs%{?_isa} = %{epoch}:%{version}-%{release}
|
||||
@ -211,6 +275,8 @@ mkdir -p %{buildroot}%{_datadir}/gdm/autostart/LoginWindow
|
||||
|
||||
mkdir -p %{buildroot}/run/gdm
|
||||
|
||||
mkdir -p %{buildroot}%{_sysconfdir}/dconf/db/gdm.d/locks
|
||||
|
||||
rm -f %{buildroot}%{_bindir}/gdm-screenshot
|
||||
|
||||
find %{buildroot} -name '*.a' -delete
|
||||
@ -303,6 +369,8 @@ fi
|
||||
%dir %{_sysconfdir}/gdm/PreSession
|
||||
%dir %{_sysconfdir}/gdm/PostSession
|
||||
%dir %{_sysconfdir}/gdm/PostLogin
|
||||
%dir %{_sysconfdir}/dconf/db/gdm.d
|
||||
%dir %{_sysconfdir}/dconf/db/gdm.d/locks
|
||||
%{_datadir}/pixmaps/*.png
|
||||
%{_datadir}/glib-2.0/schemas/org.gnome.login-screen.gschema.xml
|
||||
%{_datadir}/glib-2.0/schemas/org.gnome.login-screen.gschema.override
|
||||
@ -357,6 +425,39 @@ fi
|
||||
%{_libdir}/pkgconfig/gdm-pam-extensions.pc
|
||||
|
||||
%changelog
|
||||
* Wed Jan 27 2021 Ray Strode <rstrode@redhat.com> - 3.28.3-39
|
||||
- Ensure login screen display server is is killed at log in
|
||||
- Pull in fixes for two security issues
|
||||
Resolves: #1918391
|
||||
|
||||
* Tue Nov 10 2020 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-38
|
||||
- Re-add disabling Wayland for server GPUs
|
||||
Related: #1670273
|
||||
|
||||
* Tue Nov 10 2020 Jonas Ådahl <jadahl@redhat.com> - 3.28.3-35
|
||||
- Stop disabling Wayland for server GPUs
|
||||
Related: #1670273
|
||||
|
||||
* Tue Sep 15 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-34
|
||||
- Fix file descriptor leak
|
||||
Resolves: #1877853
|
||||
|
||||
* Tue Sep 01 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-33
|
||||
- Fix problem with Xorg fallback
|
||||
Resolves: #1868260
|
||||
|
||||
* Tue Aug 11 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-32
|
||||
- Add dconf db to file manifest
|
||||
Related: #1833158
|
||||
|
||||
* Thu Jul 23 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-31
|
||||
- add back gdm system db to dconf profile
|
||||
Resolves: #1833158
|
||||
|
||||
* Mon Jul 13 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-30
|
||||
- Make sure login screen is killed during login
|
||||
Resolves: #1618481
|
||||
|
||||
* Wed Feb 05 2020 Ray Strode <rstrode@redhat.com> - 3.28.3-29
|
||||
- Make GNOME work slightly better in the multiple logins case.
|
||||
Related: #1710882
|
||||
|
Loading…
Reference in New Issue
Block a user