import gdm-40.1-13.el9_0.4

This commit is contained in:
CentOS Sources 2022-05-17 04:44:37 -04:00 committed by Stepan Oksanichenko
commit 78eee7c83b
27 changed files with 10046 additions and 0 deletions

1
.gdm.metadata Normal file
View File

@ -0,0 +1 @@
761f14d38e1714a013ee93d6076ae55283189e2c SOURCES/gdm-40.1.tar.xz

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
SOURCES/gdm-40.1.tar.xz

View File

@ -0,0 +1,159 @@
From f6ebcec5d48aeff718a9db9b8ff812fd404a61ed Mon Sep 17 00:00:00 2001
From: Rui Matos <tiagomatos@gmail.com>
Date: Mon, 23 Jan 2017 20:19:51 +0100
Subject: [PATCH] Honor initial setup being disabled by distro installer
Sysadmins might want to disable any kind of initial setup for their
users, perhaps because they pre-configure their environments. We
already provide a configuration file option for this but distro
installers might have their own way of requesting this.
At least the anaconda installer provides an option to skip any kind
post-install setup tools so, for now we're only adding support for
that but more might be added in the future.
https://bugzilla.gnome.org/show_bug.cgi?id=777708
---
daemon/gdm-display.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 34467856..9438fe72 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -1621,103 +1621,132 @@ kernel_cmdline_initial_setup_force_state (gboolean *force_state)
GError *error = NULL;
gchar *contents = NULL;
gchar *setup_argument = NULL;
g_return_val_if_fail (force_state != NULL, FALSE);
if (!g_file_get_contents ("/proc/cmdline", &contents, NULL, &error)) {
g_debug ("GdmDisplay: Could not check kernel parameters, not forcing initial setup: %s",
error->message);
g_clear_error (&error);
return FALSE;
}
g_debug ("GdmDisplay: Checking kernel command buffer %s", contents);
if (!kernel_cmdline_initial_setup_argument (contents, &setup_argument, &error)) {
g_debug ("GdmDisplay: Failed to read kernel commandline: %s", error->message);
g_clear_pointer (&contents, g_free);
return FALSE;
}
g_clear_pointer (&contents, g_free);
/* Poor-man's check for truthy or falsey values */
*force_state = setup_argument[0] == '1';
g_free (setup_argument);
return TRUE;
}
+static gboolean
+initial_setup_disabled_by_anaconda (void)
+{
+ GKeyFile *key_file;
+ const gchar *file_name = SYSCONFDIR "/sysconfig/anaconda";
+ gboolean disabled = FALSE;
+ GError *error = NULL;
+
+ key_file = g_key_file_new ();
+ if (!g_key_file_load_from_file (key_file, file_name, G_KEY_FILE_NONE, &error)) {
+ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) &&
+ !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_NOT_FOUND)) {
+ g_warning ("Could not read %s: %s", file_name, error->message);
+ }
+ g_error_free (error);
+ goto out;
+ }
+
+ disabled = g_key_file_get_boolean (key_file, "General",
+ "post_install_tools_disabled", NULL);
+ out:
+ g_key_file_unref (key_file);
+ return disabled;
+}
+
static gboolean
wants_initial_setup (GdmDisplay *self)
{
GdmDisplayPrivate *priv;
gboolean enabled = FALSE;
gboolean forced = FALSE;
priv = gdm_display_get_instance_private (self);
if (already_done_initial_setup_on_this_boot ()) {
return FALSE;
}
if (kernel_cmdline_initial_setup_force_state (&forced)) {
if (forced) {
g_debug ("GdmDisplay: Forcing gnome-initial-setup");
return TRUE;
}
g_debug ("GdmDisplay: Forcing no gnome-initial-setup");
return FALSE;
}
/* don't run initial-setup on remote displays
*/
if (!priv->is_local) {
return FALSE;
}
/* don't run if the system has existing users */
if (priv->have_existing_user_accounts) {
return FALSE;
}
/* don't run if initial-setup is unavailable */
if (!can_create_environment ("gnome-initial-setup")) {
return FALSE;
}
if (!gdm_settings_direct_get_boolean (GDM_KEY_INITIAL_SETUP_ENABLE, &enabled)) {
return FALSE;
}
+ if (initial_setup_disabled_by_anaconda ()) {
+ return FALSE;
+ }
+
return enabled;
}
void
gdm_display_start_greeter_session (GdmDisplay *self)
{
GdmDisplayPrivate *priv;
GdmSession *session;
char *display_name;
char *seat_id;
char *hostname;
char *auth_file = NULL;
priv = gdm_display_get_instance_private (self);
g_return_if_fail (g_strcmp0 (priv->session_class, "greeter") == 0);
g_debug ("GdmDisplay: Running greeter");
display_name = NULL;
seat_id = NULL;
hostname = NULL;
g_object_get (self,
"x11-display-name", &display_name,
"seat-id", &seat_id,
"remote-hostname", &hostname,
NULL);
if (priv->access_file != NULL) {
auth_file = gdm_display_access_file_get_path (priv->access_file);
}
--
2.32.0

View File

@ -0,0 +1,103 @@
From aa1c4a7708df2edbc12f2ada7249208aef586d1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Tue, 8 Jun 2021 20:45:00 +0200
Subject: [PATCH] data: Disable network configuration on login screen
---
data/meson.build | 10 ++++++++++
data/org.gnome.gdm.rules.in | 8 ++++++++
2 files changed, 18 insertions(+)
create mode 100644 data/org.gnome.gdm.rules.in
diff --git a/data/meson.build b/data/meson.build
index 7c5222ea..20d39a36 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -130,60 +130,70 @@ pam_data_files_map = {
],
'arch': [
'gdm-autologin',
'gdm-launch-environment',
'gdm-fingerprint',
'gdm-smartcard',
'gdm-password',
],
'none': [],
# We should no longer have 'autodetect' at this point
}
pam_data_files = pam_data_files_map[default_pam_config]
pam_prefix = (get_option('pam-prefix') != '')? get_option('pam-prefix') : get_option('sysconfdir')
foreach _pam_filename : pam_data_files
install_data('pam-@0@/@1@.pam'.format(default_pam_config, _pam_filename),
rename: _pam_filename,
install_dir: pam_prefix / 'pam.d',
)
endforeach
gdm_rules = configure_file(
input: '61-gdm.rules.in',
output: '@BASENAME@',
configuration: {
'libexecdir': gdm_prefix / get_option('libexecdir'),
},
install_dir: udev_dir,
)
+# Polkit rules
+polkit_rules = configure_file(
+ input: 'org.gnome.gdm.rules.in',
+ output: '@BASENAME@',
+ configuration: {
+ 'GDM_USERNAME': get_option('user'),
+ },
+ install_dir: get_option('datadir') / 'polkit-1' / 'rules.d',
+)
+
# DBus service files
service_config = configuration_data()
service_config.set('sbindir', gdm_prefix / get_option('sbindir'))
service_config.set('GDM_INITIAL_VT', get_option('initial-vt'))
service_config.set('LANG_CONFIG_FILE', lang_config_file)
if plymouth_dep.found()
service_config.set('PLYMOUTH_QUIT_SERVICE', 'plymouth-quit.service')
else
service_config.set('PLYMOUTH_QUIT_SERVICE', '')
endif
if get_option('systemdsystemunitdir') != ''
systemd_systemunitdir = get_option('systemdsystemunitdir')
else
systemd_systemunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir')
endif
if get_option('systemduserunitdir') != ''
systemd_userunitdir = get_option('systemduserunitdir')
else
systemd_userunitdir = systemd_dep.get_pkgconfig_variable('systemduserunitdir',
define_variable: ['prefix', get_option('prefix')])
endif
configure_file(
input: 'gdm.service.in',
output: '@BASENAME@',
configuration: service_config,
install_dir: systemd_systemunitdir,
format: 'cmake'
diff --git a/data/org.gnome.gdm.rules.in b/data/org.gnome.gdm.rules.in
new file mode 100644
index 00000000..09544f11
--- /dev/null
+++ b/data/org.gnome.gdm.rules.in
@@ -0,0 +1,8 @@
+polkit.addRule(function(action, subject) {
+ if (action.id == "org.freedesktop.NetworkManager.network-control" &&
+ subject.user == "@GDM_USERNAME@") {
+ return polkit.Result.NO;
+ }
+
+ return polkit.Result.NOT_HANDLED;
+});
--
2.32.0

View File

@ -0,0 +1,24 @@
From 3e62d7b423175102bd2376adc9cf58ad736b23b0 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
This way system settings can affect the login screen.
---
data/dconf/gdm.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/data/dconf/gdm.in b/data/dconf/gdm.in
index 4d8bf174..9694078f 100644
--- a/data/dconf/gdm.in
+++ b/data/dconf/gdm.in
@@ -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.32.0

View File

@ -0,0 +1,55 @@
From a4743b9b2b355f84da3904e7da93ec3c7a521895 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 26 Jul 2019 14:06:16 -0400
Subject: [PATCH] data: reap gdm sessions on shutdown
If GDM gets shutdown we should make sure all sessions get shutdown too.
This is a bit of a safety net in case any processes in the session are
lingering after the orderly shutdown.
---
data/gdm.service.in | 1 +
1 file changed, 1 insertion(+)
diff --git a/data/gdm.service.in b/data/gdm.service.in
index 17e8a8de..195bd0fd 100644
--- a/data/gdm.service.in
+++ b/data/gdm.service.in
@@ -1,33 +1,34 @@
[Unit]
Description=GNOME Display Manager
# replaces the getty
Conflicts=getty@tty${GDM_INITIAL_VT}.service
After=getty@tty${GDM_INITIAL_VT}.service
# replaces plymouth-quit since it quits plymouth on its own
Conflicts=${PLYMOUTH_QUIT_SERVICE}
After=${PLYMOUTH_QUIT_SERVICE}
# Needs all the dependencies of the services it's replacing
# pulled from getty@.service and ${PLYMOUTH_QUIT_SERVICE}
# (except for plymouth-quit-wait.service since it waits until
# plymouth is quit, which we do)
After=rc-local.service plymouth-start.service systemd-user-sessions.service
# GDM takes responsibility for stopping plymouth, so if it fails
# for any reason, make sure plymouth still stops
OnFailure=plymouth-quit.service
[Service]
ExecStart=${sbindir}/gdm
+ExecStopPost=-/usr/bin/bash -c 'for f in /run/systemd/sessions/*; do [ -f $f ] && /usr/bin/fgrep -q SERVICE=gdm $f && loginctl terminate-session $(basename $f); done'
KillMode=mixed
Restart=always
IgnoreSIGPIPE=no
BusName=org.gnome.DisplayManager
EnvironmentFile=-${LANG_CONFIG_FILE}
ExecReload=/bin/kill -SIGHUP $MAINPID
KeyringMode=shared
[Install]
Alias=display-manager.service
--
2.32.0

View File

@ -0,0 +1,325 @@
From 9261fcd05667fc5f8b81880577e41a566db821a8 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 15 Sep 2021 11:23:17 -0400
Subject: [PATCH] local-display-factory: Don't try to respawn displays on
shutdown
At the moment in the shutdown path we may try to respawn displays
that just got killed.
The respawning happens when things are half torn down leading to
crashes.
This commit makes sure we turn off the respawn logic in the shutdown
path.
---
daemon/gdm-local-display-factory.c | 11 ++++++++++-
daemon/gdm-manager.c | 2 ++
2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 141d64c6..bca41f6e 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -46,60 +46,62 @@
#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 */
#define SEAT0_GRAPHICS_CHECK_TIMEOUT 10 /* seconds */
struct _GdmLocalDisplayFactory
{
GdmDisplayFactory parent;
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;
guint seat_properties_changed_id;
gboolean seat0_graphics_check_timed_out;
guint seat0_graphics_check_timeout_id;
#if defined(ENABLE_USER_DISPLAY_SERVER)
unsigned int active_vt;
guint active_vt_watch_id;
guint wait_to_finish_timeout_id;
#endif
+
+ gboolean is_started;
};
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 void ensure_display_for_seat (GdmLocalDisplayFactory *factory,
const char *seat_id);
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) {
@@ -416,60 +418,64 @@ on_session_registered_cb (GObject *gobject,
GParamSpec *pspec,
gpointer user_data)
{
GdmDisplay *display = GDM_DISPLAY (gobject);
GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data);
gboolean registered;
g_object_get (display, "session-registered", &registered, NULL);
if (!registered)
return;
g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill");
finish_waiting_displays_on_seat (factory, "seat0");
}
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;
+
+ if (!factory->is_started)
+ return;
+
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->used_display_numbers
so that it may be reused */
if (num != -1) {
g_hash_table_remove (factory->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 && g_strcmp0 (session_class, "greeter") != 0) {
/* reset num failures */
@@ -1204,99 +1210,102 @@ on_display_added (GdmDisplayStore *display_store,
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);
}
static gboolean
gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
{
GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
GdmDisplayStore *store;
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+ factory->is_started = TRUE;
+
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
g_signal_connect_object (G_OBJECT (store),
"display-added",
G_CALLBACK (on_display_added),
factory,
0);
g_signal_connect_object (G_OBJECT (store),
"display-removed",
G_CALLBACK (on_display_removed),
factory,
0);
gdm_local_display_factory_start_monitor (factory);
return gdm_local_display_factory_sync_seats (factory);
}
static gboolean
gdm_local_display_factory_stop (GdmDisplayFactory *base_factory)
{
GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
GdmDisplayStore *store;
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
gdm_local_display_factory_stop_monitor (factory);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
g_signal_handlers_disconnect_by_func (G_OBJECT (store),
G_CALLBACK (on_display_added),
factory);
g_signal_handlers_disconnect_by_func (G_OBJECT (store),
G_CALLBACK (on_display_removed),
factory);
-
g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove);
+ factory->is_started = FALSE;
+
return TRUE;
}
static void
gdm_local_display_factory_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_local_display_factory_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
switch (prop_id) {
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 4c2752fe..cc61efc9 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -2741,60 +2741,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);
+ gdm_manager_stop (manager);
+
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,
g_hash_table_unref);
g_clear_pointer (&manager->priv->transient_sessions,
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.32.0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,729 @@
From e5b3467412874d27c311253e3d5d7e65a61d12a4 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 1 Mar 2022 13:25:02 -0500
Subject: [PATCH 1/4] local-display-factory: Stall startup until main graphics
card is ready
At the moment, GDM waits until systemd says the system supports
graphics (via the CanGraphical logind property).
Unfortunately, this property isn't really what we need, since it flips
to true when *any* graphics are available, not when the main graphics
for the system are ready.
This is a problem on hybrid graphics systems, if one card is slower to
load than another. In particular, the vendor nvidia driver can be slow
to load because it has multiple kernel modules it loads in series.
Indeed on fast systems, that use the vendor nvidia driver, it's not
unusual for boot to get to a point where all of userspace up to and
including GDM is executed before the graphics are ready to go.
This commit tries to mitigate the situation by adding an additional,
check aside from CanGraphical to test if the system is ready.
This check waits for the graphics card associated with boot to be fully
up and running before proceeding to start a login screen.
Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/763
---
daemon/gdm-local-display-factory.c | 164 ++++++++++++++++++++++++++---
daemon/meson.build | 4 +
meson.build | 2 +
4 files changed, 159 insertions(+), 12 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index c00e1c47..0b1d3482 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -1,100 +1,112 @@
/* -*- 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>
+#ifdef HAVE_UDEV
+#include <gudev/gudev.h>
+#endif
+
#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_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 */
#define SEAT0_GRAPHICS_CHECK_TIMEOUT 10 /* seconds */
struct _GdmLocalDisplayFactory
{
- GdmDisplayFactory parent;
+ GdmDisplayFactory parent;
+#ifdef HAVE_UDEV
+ GUdevClient *gudev_client;
+#endif
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;
guint seat_properties_changed_id;
+ gboolean seat0_has_platform_graphics;
+ gboolean seat0_has_boot_up_graphics;
+
gboolean seat0_graphics_check_timed_out;
guint seat0_graphics_check_timeout_id;
+ gulong uevent_handler_id;
+
#if defined(ENABLE_USER_DISPLAY_SERVER)
unsigned int active_vt;
guint active_vt_watch_id;
guint wait_to_finish_timeout_id;
#endif
gboolean is_started;
};
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 void ensure_display_for_seat (GdmLocalDisplayFactory *factory,
const char *seat_id);
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);
@@ -594,142 +606,236 @@ lookup_by_seat_id (const char *id,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &current, 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);
}
+#ifdef HAVE_UDEV
+static gboolean
+udev_is_settled (GdmLocalDisplayFactory *factory)
+{
+ g_autoptr (GUdevEnumerator) enumerator = NULL;
+ GList *devices;
+ GList *node;
+
+ gboolean is_settled = FALSE;
+
+ if (factory->seat0_has_platform_graphics) {
+ g_debug ("GdmLocalDisplayFactory: udev settled, platform graphics enabled.");
+ return TRUE;
+ }
+
+ if (factory->seat0_has_boot_up_graphics) {
+ g_debug ("GdmLocalDisplayFactory: udev settled, boot up graphics available.");
+ return TRUE;
+ }
+
+ if (factory->seat0_graphics_check_timed_out) {
+ g_debug ("GdmLocalDisplayFactory: udev timed out, proceeding anyway.");
+ return TRUE;
+ }
+
+ g_debug ("GdmLocalDisplayFactory: Checking if udev has settled enough to support graphics.");
+
+ enumerator = g_udev_enumerator_new (factory->gudev_client);
+
+ g_udev_enumerator_add_match_name (enumerator, "card*");
+ g_udev_enumerator_add_match_tag (enumerator, "master-of-seat");
+ g_udev_enumerator_add_match_subsystem (enumerator, "drm");
+
+ devices = g_udev_enumerator_execute (enumerator);
+ if (!devices) {
+ g_debug ("GdmLocalDisplayFactory: udev has no candidate graphics devices available yet.");
+ return FALSE;
+ }
+
+ node = devices;
+ while (node != NULL) {
+ GUdevDevice *device = node->data;
+ GList *next_node = node->next;
+ g_autoptr (GUdevDevice) platform_device = NULL;
+ g_autoptr (GUdevDevice) pci_device = NULL;
+
+ platform_device = g_udev_device_get_parent_with_subsystem (device, "platform", NULL);
+
+ if (platform_device != NULL) {
+ g_debug ("GdmLocalDisplayFactory: Found embedded platform graphics, proceeding.");
+ factory->seat0_has_platform_graphics = TRUE;
+ is_settled = TRUE;
+ break;
+ }
+
+ pci_device = g_udev_device_get_parent_with_subsystem (device, "pci", NULL);
+
+ if (pci_device != NULL) {
+ gboolean boot_vga;
+
+ boot_vga = g_udev_device_get_sysfs_attr_as_int (pci_device, "boot_vga");
+
+ if (boot_vga == 1) {
+ g_debug ("GdmLocalDisplayFactory: Found primary PCI graphics adapter, proceeding.");
+ factory->seat0_has_boot_up_graphics = TRUE;
+ is_settled = TRUE;
+ break;
+ } else {
+ g_debug ("GdmLocalDisplayFactory: Found secondary PCI graphics adapter, not proceeding yet.");
+ }
+ }
+ node = next_node;
+ }
+
+ g_debug ("GdmLocalDisplayFactory: udev has %ssettled enough for graphics.", is_settled? "" : "not ");
+ g_list_free_full (devices, g_object_unref);
+
+ if (is_settled)
+ g_clear_signal_handler (&factory->uevent_handler_id, factory->gudev_client);
+
+ return is_settled;
+}
+#endif
+
static int
on_seat0_graphics_check_timeout (gpointer user_data)
{
GdmLocalDisplayFactory *factory = user_data;
factory->seat0_graphics_check_timeout_id = 0;
/* Simply try to re-add seat0. If it is there already (i.e. CanGraphical
* turned TRUE, then we'll find it and it will not be created again).
*/
factory->seat0_graphics_check_timed_out = TRUE;
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_REMOVE;
}
static void
ensure_display_for_seat (GdmLocalDisplayFactory *factory,
const char *seat_id)
{
int ret;
gboolean seat_supports_graphics;
gboolean is_seat0;
g_auto (GStrv) session_types = NULL;
const char *legacy_session_types[] = { "x11", NULL };
GdmDisplayStore *store;
GdmDisplay *display = NULL;
g_autofree char *login_session_id = NULL;
gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
g_autofree gchar *preferred_display_server = NULL;
gboolean falling_back = FALSE;
+ gboolean waiting_on_udev = FALSE;
gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
preferred_display_server = get_preferred_display_server (factory);
if (g_strcmp0 (preferred_display_server, "none") == 0) {
g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
return;
}
- ret = sd_seat_can_graphical (seat_id);
+#ifdef HAVE_UDEV
+ waiting_on_udev = !udev_is_settled (factory);
+#endif
- if (ret < 0) {
- g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
- return;
- }
+ if (!waiting_on_udev) {
+ ret = sd_seat_can_graphical (seat_id);
- if (ret == 0) {
- g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
- seat_supports_graphics = FALSE;
+ if (ret < 0) {
+ g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
+ return;
+ }
+
+ if (ret == 0) {
+ g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
+ seat_supports_graphics = FALSE;
+ } else {
+ g_debug ("GdmLocalDisplayFactory: System supports graphics");
+ seat_supports_graphics = TRUE;
+ }
} else {
- g_debug ("GdmLocalDisplayFactory: System supports graphics");
- seat_supports_graphics = TRUE;
+ g_debug ("GdmLocalDisplayFactory: udev is still settling, so not creating display yet");
+ seat_supports_graphics = FALSE;
}
if (g_strcmp0 (seat_id, "seat0") == 0) {
is_seat0 = TRUE;
falling_back = factory->num_failures > 0;
session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
if (session_types == NULL) {
g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
seat_supports_graphics = FALSE;
} else {
g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
session_types[0], falling_back? " fallback" : "");
}
} else {
is_seat0 = FALSE;
g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
/* Force legacy X11 for all auxiliary seats */
seat_supports_graphics = TRUE;
session_types = g_strdupv ((char **) legacy_session_types);
}
/* For seat0, we have a fallback logic to still try starting it after
* SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if
- * CanGraphical is unset.
+ * CanGraphical is unset or udev otherwise never finds a suitable graphics card.
* This is ugly, but it means we'll come up eventually in some
* scenarios where no master device is present.
* Note that we'll force an X11 fallback even though there might be
* cases where an wayland capable device is present and simply not marked as
* master-of-seat. In these cases, this should likely be fixed in the
* udev rules.
*
* At the moment, systemd always sets CanGraphical for non-seat0 seats.
* This is because non-seat0 seats are defined by having master-of-seat
* set. This means we can avoid the fallback check for non-seat0 seats,
* which simplifies the code.
*/
if (is_seat0) {
if (!seat_supports_graphics) {
if (!factory->seat0_graphics_check_timed_out) {
if (factory->seat0_graphics_check_timeout_id == 0) {
g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT);
factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT,
on_seat0_graphics_check_timeout,
factory);
} else {
/* It is not yet time to force X11 fallback. */
g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout.");
}
return;
}
g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!");
@@ -1138,113 +1240,151 @@ on_vt_changed (GIOChannel *source,
if (factory->wait_to_finish_timeout_id != 0) {
g_debug ("GdmLocalDisplayFactory: deferring previous login screen clean up operation");
g_source_remove (factory->wait_to_finish_timeout_id);
}
factory->wait_to_finish_timeout_id = g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
(GSourceFunc)
on_finish_waiting_for_seat0_displays_timeout,
factory);
}
}
}
/* 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 (factory->active_vt != GDM_INITIAL_VT) {
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_CONTINUE;
}
#endif
+#ifdef HAVE_UDEV
+static void
+on_uevent (GUdevClient *client,
+ const char *action,
+ GUdevDevice *device,
+ GdmLocalDisplayFactory *factory)
+{
+ if (!g_udev_device_get_device_file (device))
+ return;
+
+ if (g_strcmp0 (action, "add") != 0 &&
+ g_strcmp0 (action, "change") != 0)
+ return;
+
+ if (!udev_is_settled (factory))
+ return;
+
+ g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id);
+ factory->uevent_handler_id = 0;
+
+ ensure_display_for_seat (factory, "seat0");
+}
+#endif
+
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
+ const char *subsystems[] = { "drm", NULL };
factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->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->seat_removed_id = g_dbus_connection_signal_subscribe (factory->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);
factory->seat_properties_changed_id = g_dbus_connection_signal_subscribe (factory->connection,
"org.freedesktop.login1",
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
NULL,
"org.freedesktop.login1.Seat",
G_DBUS_SIGNAL_FLAGS_MATCH_ARG0_NAMESPACE,
on_seat_properties_changed,
g_object_ref (factory),
g_object_unref);
+#ifdef HAVE_UDEV
+ factory->gudev_client = g_udev_client_new (subsystems);
+ factory->uevent_handler_id = g_signal_connect (factory->gudev_client,
+ "uevent",
+ G_CALLBACK (on_uevent),
+ factory);
+#endif
#if defined(ENABLE_USER_DISPLAY_SERVER)
io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
if (io_channel != NULL) {
factory->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->uevent_handler_id) {
+ g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id);
+ factory->uevent_handler_id = 0;
+ }
+ g_clear_object (&factory->gudev_client);
+
if (factory->seat_new_id) {
g_dbus_connection_signal_unsubscribe (factory->connection,
factory->seat_new_id);
factory->seat_new_id = 0;
}
if (factory->seat_removed_id) {
g_dbus_connection_signal_unsubscribe (factory->connection,
factory->seat_removed_id);
factory->seat_removed_id = 0;
}
if (factory->seat_properties_changed_id) {
g_dbus_connection_signal_unsubscribe (factory->connection,
factory->seat_properties_changed_id);
factory->seat_properties_changed_id = 0;
}
#if defined(ENABLE_USER_DISPLAY_SERVER)
if (factory->active_vt_watch_id) {
g_source_remove (factory->active_vt_watch_id);
factory->active_vt_watch_id = 0;
}
if (factory->wait_to_finish_timeout_id != 0) {
g_source_remove (factory->wait_to_finish_timeout_id);
factory->wait_to_finish_timeout_id = 0;
}
#endif
}
static void
on_display_added (GdmDisplayStore *display_store,
const char *id,
diff --git a/daemon/meson.build b/daemon/meson.build
index 2e61b644..41f30abe 100644
--- a/daemon/meson.build
+++ b/daemon/meson.build
@@ -177,37 +177,41 @@ gdm_daemon_sources = files(
'gdm-session-record.c',
'gdm-session-worker-common.c',
'gdm-session-worker-job.c',
'gdm-session.c',
'main.c',
)
gdm_daemon_gen_sources = [
display_dbus_gen,
local_display_factory_dbus_gen,
manager_dbus_gen,
local_display_dbus_gen,
session_dbus_gen,
session_worker_dbus_gen,
gdm_session_enums,
]
if xdmcp_dep.found()
gdm_daemon_deps += xdmcp_dep
gdm_daemon_sources = [
gdm_daemon_sources,
files(
'gdm-xdmcp-display-factory.c',
'gdm-xdmcp-display.c',
'gdm-xdmcp-chooser-display.c',
),
]
endif
+if gudev_dep.found()
+ gdm_daemon_deps += gudev_dep
+endif
+
gdm_daemon = executable('gdm',
[ gdm_daemon_sources, gdm_daemon_gen_sources ],
dependencies: gdm_daemon_deps,
include_directories: config_h_dir,
install: true,
install_dir: get_option('sbindir')
)
diff --git a/meson.build b/meson.build
index 02d609dc..05d8da41 100644
--- a/meson.build
+++ b/meson.build
@@ -11,60 +11,61 @@ i18n = import('i18n')
# Compiler
cc = meson.get_compiler('c')
# Options
gdm_prefix = get_option('prefix')
gdmconfdir = (get_option('sysconfsubdir') == '')? gdm_prefix / get_option('sysconfdir') : gdm_prefix / get_option('sysconfdir') / get_option('sysconfsubdir')
dmconfdir = (get_option('dmconfdir') != '')? get_option('dmconfdir') : gdm_prefix / get_option('sysconfdir') / 'dm'
udev_dir = get_option('udev-dir')
at_spi_registryd_dir = (get_option('at-spi-registryd-dir') != '')? get_option('at-spi-registryd-dir') : gdm_prefix / get_option('libexecdir')
lang_config_file = (get_option('lang-file') != '')? get_option('lang-file') : gdm_prefix / get_option('sysconfdir') / 'locale.conf'
pam_mod_dir = (get_option('pam-mod-dir') != '')? get_option('pam-mod-dir') : gdm_prefix / get_option('libdir') / 'security'
dbus_sys_dir = (get_option('dbus-sys') != '')? get_option('dbus-sys') : get_option('sysconfdir') / 'dbus-1' / 'system.d'
gdm_defaults_conf = (get_option('defaults-conf') != '')? get_option('defaults-conf') : gdm_prefix / get_option('datadir') / 'gdm' / 'defaults.conf'
gdm_custom_conf = (get_option('custom-conf') != '')? get_option('custom-conf') : gdmconfdir / 'custom.conf'
gnome_settings_daemon_dir = (get_option('gnome-settings-daemon-dir') != '')? get_option('gnome-settings-daemon-dir') : gdm_prefix / get_option('libexecdir')
gdm_run_dir = (get_option('run-dir') != '')? get_option('run-dir') : gdm_prefix / get_option('localstatedir') / 'run' / 'gdm'
gdm_runtime_conf = (get_option('runtime-conf') != '')? get_option('runtime-conf') : gdm_run_dir / 'custom.conf'
gdm_pid_file = (get_option('pid-file') != '')? get_option('pid-file') : gdm_run_dir / 'gdm.pid'
ran_once_marker_dir = (get_option('ran-once-marker-dir') != '')? get_option('ran-once-marker-dir') : gdm_run_dir
working_dir = (get_option('working-dir') != '')? get_option('working-dir') : gdm_prefix / get_option('localstatedir') / 'lib' / 'gdm'
gdm_xauth_dir = (get_option('xauth-dir') != '')? get_option('xauth-dir') : gdm_run_dir
gdm_screenshot_dir = (get_option('screenshot-dir') != '')? get_option('screenshot-dir') : gdm_run_dir / 'greeter'
# Common variables
config_h_dir = include_directories('.')
# Dependencies
udev_dep = dependency('udev')
+gudev_dep = dependency('gudev-1.0', version: '>= 232')
glib_min_version = '2.56.0'
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version)
gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1')
libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4')
accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35')
xcb_dep = dependency('xcb')
keyutils_dep = dependency('libkeyutils', required: false)
libselinux_dep = dependency('libselinux', required: get_option('selinux'))
# udev
if udev_dir == ''
if udev_dep.found()
udev_prefix = udev_dep.get_pkgconfig_variable('udevdir')
else
udev_prefix = gdm_prefix / 'lib' / 'udev'
endif
udev_dir = udev_prefix / 'rules.d'
endif
# X11
x_deps = declare_dependency(
dependencies: [
dependency('x11'),
dependency('xau'),
],
@@ -217,60 +218,61 @@ conf.set('HAVE_UTMP_H', have_utmp_header)
conf.set('HAVE_UTMPX_H', have_utmpx_header)
conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r)
conf.set('UTMP', utmp_struct)
conf.set('HAVE_GETUTXENT', cc.has_function('getutxent'))
conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp'))
conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx'))
conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil'))
conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil'))
conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil'))
conf.set('HAVE_PAM_SYSLOG', have_pam_syslog)
conf.set('HAVE_KEYUTILS', keyutils_dep.found())
conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported)
conf.set('HAVE_SELINUX', libselinux_dep.found())
conf.set('HAVE_XSERVER_WITH_LISTEN', xserver_has_listen)
conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server'))
conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal'))
conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support'))
conf.set('ENABLE_PROFILING', get_option('profiling'))
conf.set('GDM_INITIAL_VT', get_option('initial-vt'))
conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf)
conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf)
conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf)
conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path'))
conf.set_quoted('GDM_USERNAME', get_option('user'))
conf.set_quoted('GDM_GROUPNAME', get_option('group'))
conf.set('HAVE_LIBXDMCP', xdmcp_dep.found())
conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server)
conf.set('WITH_PLYMOUTH', plymouth_dep.found())
conf.set_quoted('X_SERVER', x_bin)
conf.set_quoted('X_PATH', x_path)
+conf.set('HAVE_UDEV', gudev_dep.found())
conf.set('HAVE_UT_UT_HOST', utmp_has_host_field)
conf.set('HAVE_UT_UT_PID', utmp_has_pid_field)
conf.set('HAVE_UT_UT_ID', utmp_has_id_field)
conf.set('HAVE_UT_UT_NAME', utmp_has_name_field)
conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field)
conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field)
conf.set('HAVE_UT_UT_USER', utmp_has_user_field)
conf.set('HAVE_UT_UT_TIME', utmp_has_time_field)
conf.set('HAVE_UT_UT_TV', utmp_has_tv_field)
conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field)
conf.set('ENABLE_IPV6', get_option('ipv6'))
configure_file(output: 'config.h', configuration: conf)
# Subdirs
subdir('data')
subdir('common')
if pam_extensions_supported
subdir('pam-extensions')
endif
subdir('daemon')
subdir('libgdm')
subdir('utils')
subdir('pam_gdm')
subdir('po')
if libcheck_dep.found()
subdir('tests')
endif
if xdmcp_dep.found()
subdir('chooser')
endif
--
2.34.1

View File

@ -0,0 +1,344 @@
From 2e7965beae81e0e93d3f475f2ea29a7af6c23f29 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 20 Dec 2018 14:51:38 -0500
Subject: [PATCH 1/3] manager: allow multiple xdmcp logins for the same user
---
common/gdm-settings-keys.h | 1 +
daemon/gdm-manager.c | 71 ++++++++++++++++++++++++++++----------
data/gdm.schemas.in | 5 +++
3 files changed, 59 insertions(+), 18 deletions(-)
diff --git a/common/gdm-settings-keys.h b/common/gdm-settings-keys.h
index 87685d3c..4b3a1ffe 100644
--- a/common/gdm-settings-keys.h
+++ b/common/gdm-settings-keys.h
@@ -30,37 +30,38 @@ G_BEGIN_DECLS
#define GDM_KEY_AUTO_LOGIN_ENABLE "daemon/AutomaticLoginEnable"
#define GDM_KEY_AUTO_LOGIN_USER "daemon/AutomaticLogin"
#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable"
#define GDM_KEY_TIMED_LOGIN_USER "daemon/TimedLogin"
#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay"
#define GDM_KEY_INITIAL_SETUP_ENABLE "daemon/InitialSetupEnable"
#define GDM_KEY_PREFERRED_DISPLAY_SERVER "daemon/PreferredDisplayServer"
#define GDM_KEY_WAYLAND_ENABLE "daemon/WaylandEnable"
#define GDM_KEY_XORG_ENABLE "daemon/XorgEnable"
#define GDM_KEY_DEBUG "debug/Enable"
#define GDM_KEY_INCLUDE "greeter/Include"
#define GDM_KEY_EXCLUDE "greeter/Exclude"
#define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll"
#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP"
#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin"
#define GDM_KEY_XDMCP_ENABLE "xdmcp/Enable"
#define GDM_KEY_SHOW_LOCAL_GREETER "xdmcp/ShowLocalGreeter"
#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending"
#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions"
#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait"
#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost"
#define GDM_KEY_UDP_PORT "xdmcp/Port"
#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect"
#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect"
#define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds"
#define GDM_KEY_WILLING "xdmcp/Willing"
+#define GDM_KEY_ALLOW_MULTIPLE_SESSIONS_PER_USER "xdmcp/AllowMultipleSessionsPerUser"
#define GDM_KEY_MULTICAST "chooser/Multicast"
#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr"
G_END_DECLS
#endif /* _GDM_SETTINGS_KEYS_H */
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index cc61efc9..dc839aeb 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -566,93 +566,106 @@ get_display_and_details_for_bus_sender (GdmManager *self,
*out_tty = get_tty_for_session_id (session_id, &error);
if (error != NULL) {
g_debug ("GdmManager: Error while retrieving tty for session: %s",
error->message);
g_clear_error (&error);
}
}
display = gdm_display_store_find (self->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
out:
if (out_display != NULL) {
*out_display = display;
}
g_free (session_id);
}
static gboolean
switch_to_compatible_user_session (GdmManager *manager,
GdmSession *session,
gboolean fail_if_already_switched)
{
gboolean res;
gboolean ret;
const char *username;
const char *seat_id;
- const char *ssid_to_activate;
+ const char *ssid_to_activate = NULL;
GdmSession *existing_session;
ret = FALSE;
username = gdm_session_get_username (session);
seat_id = gdm_session_get_display_seat_id (session);
- if (!fail_if_already_switched) {
- session = NULL;
- }
+ if (!fail_if_already_switched)
+ ssid_to_activate = gdm_session_get_session_id (session);
- existing_session = find_session_for_user_on_seat (manager, username, seat_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 (existing_session != NULL) {
- ssid_to_activate = gdm_session_get_session_id (existing_session);
- if (seat_id != NULL) {
- 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;
- }
+ if (!fail_if_already_switched) {
+ session = NULL;
}
- res = session_unlock (manager, ssid_to_activate);
- if (!res) {
- /* this isn't fatal */
- g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate);
+ 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);
}
- } else {
+ }
+
+ if (ssid_to_activate == NULL) {
goto out;
}
+ if (seat_id != NULL) {
+ 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;
}
return g_object_get_data (G_OBJECT (display), "gdm-user-session");
}
static gboolean
add_session_record (GdmManager *manager,
GdmSession *session,
GPid pid,
SessionRecord record)
{
const char *username;
char *display_name, *hostname, *display_device;
@@ -1089,92 +1102,114 @@ open_temporary_reauthentication_channel (GdmManager *self,
g_signal_connect (session,
"client-disconnected",
G_CALLBACK (on_reauthentication_client_disconnected),
self);
g_signal_connect (session,
"client-rejected",
G_CALLBACK (on_reauthentication_client_rejected),
self);
g_signal_connect (session,
"cancelled",
G_CALLBACK (on_reauthentication_cancelled),
self);
g_signal_connect (session,
"conversation-started",
G_CALLBACK (on_reauthentication_conversation_started),
self);
g_signal_connect (session,
"conversation-stopped",
G_CALLBACK (on_reauthentication_conversation_stopped),
self);
g_signal_connect (session,
"verification-complete",
G_CALLBACK (on_reauthentication_verification_complete),
self);
address = gdm_session_get_server_address (session);
return g_strdup (address);
}
+static gboolean
+remote_users_can_log_in_more_than_once (GdmManager *manager)
+{
+ gboolean enabled;
+
+ enabled = FALSE;
+
+ gdm_settings_direct_get_boolean (GDM_KEY_ALLOW_MULTIPLE_SESSIONS_PER_USER, &enabled);
+
+ g_debug ("GdmDisplay: Remote users allowed to log in more than once: %s", enabled? "yes" : "no");
+
+ return enabled;
+}
+
static gboolean
gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager,
GDBusMethodInvocation *invocation,
const char *username)
{
GdmManager *self = GDM_MANAGER (manager);
const char *sender;
GdmDisplay *display = NULL;
GdmSession *session;
GDBusConnection *connection;
char *seat_id = NULL;
char *session_id = NULL;
GPid pid = 0;
uid_t uid = (uid_t) -1;
gboolean is_login_screen = FALSE;
gboolean is_remote = FALSE;
g_debug ("GdmManager: trying to open reauthentication channel for user %s", username);
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, &seat_id, &session_id, NULL, &pid, &uid, &is_login_screen, &is_remote);
if (session_id == NULL || pid == 0 || uid == (uid_t) -1) {
g_dbus_method_invocation_return_error_literal (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
_("No session available"));
return TRUE;
}
+ if (is_login_screen && is_remote && remote_users_can_log_in_more_than_once (self)) {
+ g_dbus_method_invocation_return_error_literal (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_ACCESS_DENIED,
+ "Login screen creates new sessions for remote connections");
+ return TRUE;
+ }
+
if (is_login_screen) {
g_debug ("GdmManager: looking for login screen session for user %s on seat %s", username, seat_id);
session = find_session_for_user_on_seat (self,
username,
seat_id,
NULL);
} else {
g_debug ("GdmManager: looking for user session on display");
session = get_user_session_for_display (display);
}
if (session != NULL && gdm_session_is_running (session)) {
gdm_session_start_reauthentication (session, pid, uid);
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);
diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in
index a1035f95..929d13d9 100644
--- a/data/gdm.schemas.in
+++ b/data/gdm.schemas.in
@@ -112,33 +112,38 @@
<schema>
<key>xdmcp/DisplaysPerHost</key>
<signature>i</signature>
<default>1</default>
</schema>
<schema>
<key>xdmcp/Port</key>
<signature>i</signature>
<default>177</default>
</schema>
<schema>
<key>xdmcp/HonorIndirect</key>
<signature>b</signature>
<default>true</default>
</schema>
<schema>
<key>xdmcp/MaxWaitIndirect</key>
<signature>i</signature>
<default>30</default>
</schema>
<schema>
<key>xdmcp/PingIntervalSeconds</key>
<signature>i</signature>
<default>0</default>
</schema>
<schema>
<key>xdmcp/Willing</key>
<signature>s</signature>
<default>@gdmconfdir@/Xwilling</default>
</schema>
+ <schema>
+ <key>xdmcp/AllowMultipleSessionsPerUser</key>
+ <signature>b</signature>
+ <default>false</default>
+ </schema>
</schemalist>
</gdmschemafile>
--
2.32.0

View File

@ -0,0 +1,144 @@
From b8caa1a18f284cc9b59a2e0273780a51b6fd7528 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Thu, 7 Oct 2021 18:22:11 -0700
Subject: [PATCH 1/2] meson: Fix detection of Xorg versions that need -listen
tcp
Closes #704
---
meson.build | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/meson.build b/meson.build
index 64b98628..52ac1941 100644
--- a/meson.build
+++ b/meson.build
@@ -42,60 +42,63 @@ udev_dep = dependency('udev')
glib_min_version = '2.56.0'
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version)
gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1')
libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4')
accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35')
xcb_dep = dependency('xcb')
keyutils_dep = dependency('libkeyutils', required: false)
libselinux_dep = dependency('libselinux', required: get_option('selinux'))
# udev
if udev_dir == ''
if udev_dep.found()
udev_prefix = udev_dep.get_pkgconfig_variable('udevdir')
else
udev_prefix = gdm_prefix / 'lib' / 'udev'
endif
udev_dir = udev_prefix / 'rules.d'
endif
# X11
x_deps = declare_dependency(
dependencies: [
dependency('x11'),
dependency('xau'),
],
)
+# Xserver 1.17 & later default to -nolisten and require -listen for remote access
+xserver_deps = dependency('xorg-server', version : '>=1.17', required : false)
+xserver_nolisten_default = xserver_deps.found()
find_x_server_script = find_program('build-aux/find-x-server.sh', native: true)
find_x_server_out = run_command(find_x_server_script).stdout().strip()
if find_x_server_out != ''
x_bin = find_x_server_out
x_bin_path_split = x_bin.split('/')
i = 0
x_path = '/'
foreach dir : x_bin_path_split
if i < x_bin_path_split.length() - 1
x_path = x_path / dir
endif
i = i + 1
endforeach
else
# what to do, what to do, this is wrong, but this just sets the
# defaults, perhaps this user is cross compiling or some such
x_path = '/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin'
x_bin = '/usr/bin/X'
endif
xdmcp_dep = cc.find_library('Xdmcp', required: get_option('xdmcp'))
if xdmcp_dep.found() and get_option('tcp-wrappers')
libwrap_dep = cc.find_library('wrap')
endif
# systemd
systemd_dep = dependency('systemd')
libsystemd_dep = dependency('libsystemd')
if meson.version().version_compare('>= 0.53')
systemd_multiseat_x = find_program('systemd-multi-seat-x',
required: false,
dirs: [
@@ -197,60 +200,61 @@ conf.set_quoted('SYSCONFDIR', gdm_prefix / get_option('sysconfdir'))
conf.set_quoted('BINDIR', gdm_prefix / get_option('bindir'))
conf.set_quoted('LIBDIR', gdm_prefix / get_option('libdir'))
conf.set_quoted('LIBEXECDIR', gdm_prefix / get_option('libexecdir'))
conf.set_quoted('LOGDIR', get_option('log-dir'))
conf.set_quoted('DMCONFDIR', dmconfdir)
conf.set_quoted('GDMCONFDIR', gdmconfdir)
conf.set_quoted('GDM_SCREENSHOT_DIR', gdm_screenshot_dir)
conf.set_quoted('GDM_XAUTH_DIR', gdm_xauth_dir)
conf.set_quoted('GDM_RAN_ONCE_MARKER_DIR', ran_once_marker_dir)
conf.set_quoted('GDM_RUN_DIR', gdm_run_dir)
conf.set_quoted('GNOMELOCALEDIR', gdm_prefix / get_option('localedir'))
conf.set_quoted('AT_SPI_REGISTRYD_DIR', at_spi_registryd_dir)
conf.set_quoted('GDM_PID_FILE', gdm_pid_file)
conf.set_quoted('GNOME_SETTINGS_DAEMON_DIR', gnome_settings_daemon_dir)
conf.set_quoted('LANG_CONFIG_FILE', lang_config_file)
conf.set('HAVE_ADT', have_adt)
conf.set('HAVE_UTMP_H', have_utmp_header)
conf.set('HAVE_UTMPX_H', have_utmpx_header)
conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r)
conf.set('UTMP', utmp_struct)
conf.set('HAVE_GETUTXENT', cc.has_function('getutxent'))
conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp'))
conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx'))
conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil'))
conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil'))
conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil'))
conf.set('HAVE_PAM_SYSLOG', have_pam_syslog)
conf.set('HAVE_KEYUTILS', keyutils_dep.found())
conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported)
conf.set('HAVE_SELINUX', libselinux_dep.found())
+conf.set('HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY', xserver_nolisten_default)
conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server'))
conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal'))
conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support'))
conf.set('ENABLE_PROFILING', get_option('profiling'))
conf.set('GDM_INITIAL_VT', get_option('initial-vt'))
conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf)
conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf)
conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf)
conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path'))
conf.set_quoted('GDM_USERNAME', get_option('user'))
conf.set_quoted('GDM_GROUPNAME', get_option('group'))
conf.set('HAVE_LIBXDMCP', xdmcp_dep.found())
conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server)
conf.set('WITH_PLYMOUTH', plymouth_dep.found())
conf.set_quoted('X_SERVER', x_bin)
conf.set_quoted('X_PATH', x_path)
conf.set('HAVE_UT_UT_HOST', utmp_has_host_field)
conf.set('HAVE_UT_UT_PID', utmp_has_pid_field)
conf.set('HAVE_UT_UT_ID', utmp_has_id_field)
conf.set('HAVE_UT_UT_NAME', utmp_has_name_field)
conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field)
conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field)
conf.set('HAVE_UT_UT_USER', utmp_has_user_field)
conf.set('HAVE_UT_UT_TIME', utmp_has_time_field)
conf.set('HAVE_UT_UT_TV', utmp_has_tv_field)
conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field)
conf.set('ENABLE_IPV6', get_option('ipv6'))
configure_file(output: 'config.h', configuration: conf)
# Subdirs
--
2.34.1

View File

@ -0,0 +1,89 @@
From 8a29f79124f38e2106b263bacb6b5ab4cdb255d0 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 9 Mar 2022 10:46:21 -0500
Subject: [PATCH] session-settings: Fetch session from user even if user isn't
cached
Now that accountsservice supports session templates, GDM can't assume
that no-cache file means, there's nothing worth reading.
Unfortunately, GDM does exactly that. It bypasses fetching the users
session if it doesn't think the user has one.
This commit removes that no-longer-correct optimization.
---
daemon/gdm-session-settings.c | 4 ----
1 file changed, 4 deletions(-)
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
index 5b64cb65..fbf6897b 100644
--- a/daemon/gdm-session-settings.c
+++ b/daemon/gdm-session-settings.c
@@ -270,64 +270,60 @@ gdm_session_settings_new (void)
GdmSessionSettings *settings;
settings = g_object_new (GDM_TYPE_SESSION_SETTINGS,
NULL);
return settings;
}
gboolean
gdm_session_settings_is_loaded (GdmSessionSettings *settings)
{
if (settings->priv->user == NULL) {
return FALSE;
}
return act_user_is_loaded (settings->priv->user);
}
static void
load_settings_from_user (GdmSessionSettings *settings)
{
const char *session_name;
const char *session_type;
const char *language_name;
if (!act_user_is_loaded (settings->priv->user)) {
g_warning ("GdmSessionSettings: trying to load user settings from unloaded user");
return;
}
- /* if the user doesn't have saved state, they don't have any settings worth reading */
- if (!act_user_get_saved (settings->priv->user))
- goto out;
-
session_type = act_user_get_session_type (settings->priv->user);
session_name = act_user_get_session (settings->priv->user);
g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type);
if (session_type != NULL && session_type[0] != '\0') {
gdm_session_settings_set_session_type (settings, session_type);
}
if (session_name != NULL && session_name[0] != '\0') {
gdm_session_settings_set_session_name (settings, session_name);
}
language_name = act_user_get_language (settings->priv->user);
g_debug ("GdmSessionSettings: saved language is %s", language_name);
if (language_name != NULL && language_name[0] != '\0') {
gdm_session_settings_set_language_name (settings, language_name);
}
out:
g_object_notify (G_OBJECT (settings), "is-loaded");
}
static void
on_user_is_loaded_changed (ActUser *user,
GParamSpec *pspec,
GdmSessionSettings *settings)
{
if (act_user_is_loaded (settings->priv->user)) {
--
2.34.1

View File

@ -0,0 +1,84 @@
From 26705ee64f4d3628eaaf45db980c435fa26e112a Mon Sep 17 00:00:00 2001
From: Chingkai Chu <3013329+chuchingkai@users.noreply.github.com>
Date: Thu, 12 Aug 2021 10:34:01 +0800
Subject: [PATCH] session-worker: Set session_vt=0 out of pam uninitialization
MR GNOME/gdm!123 moved jump_to_vt and session_vt reseting to a
separate function, so we don't need to reset session_vt in pam
uninitialization.
https://gitlab.gnome.org/GNOME/gdm/-/issues/719
---
daemon/gdm-session-worker.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 7d7d2496..3ad94e2a 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -1076,62 +1076,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);
- 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) {
--
2.32.0

View File

@ -0,0 +1,122 @@
From 36b9fd4f6e055e236175979d9a1527df71aeac1f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 14 Sep 2021 11:00:33 -0400
Subject: [PATCH 1/5] xdmcp-display-factory: Set supported session types for
XDMCP displays
The lower levels of GDM now expect the session types supported by a
display to be specified up front.
This commit makes sure XDMCP displays do that.
---
daemon/gdm-xdmcp-display-factory.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
index ce8f026e..abb58fae 100644
--- a/daemon/gdm-xdmcp-display-factory.c
+++ b/daemon/gdm-xdmcp-display-factory.c
@@ -2104,94 +2104,100 @@ on_display_status_changed (GdmDisplay *display,
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;
+ const char *session_types[] = { "x11", NULL };
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
hostname ? hostname : "(null)", displaynum);
use_chooser = FALSE;
if (factory->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,
displaynum,
address,
get_next_session_serial (factory));
g_signal_connect (display, "hostname-selected", G_CALLBACK (on_hostname_selected), factory);
} else {
display = gdm_xdmcp_display_new (hostname,
displaynum,
address,
get_next_session_serial (factory));
}
if (display == NULL) {
goto out;
}
+ g_object_set (G_OBJECT (display),
+ "session-type", session_types[0],
+ "supported-session-types", session_types,
+ NULL);
+
if (! gdm_display_prepare (display)) {
gdm_display_unmanage (display);
g_object_unref (display);
display = NULL;
goto out;
}
g_signal_connect_after (display,
"notify::status",
G_CALLBACK (on_display_status_changed),
factory);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
gdm_display_store_add (store, display);
factory->num_pending_sessions++;
out:
return display;
}
static void
gdm_xdmcp_send_accept (GdmXdmcpDisplayFactory *factory,
GdmAddress *address,
CARD32 session_id,
ARRAY8Ptr authentication_name,
ARRAY8Ptr authentication_data,
ARRAY8Ptr authorization_name,
ARRAY8Ptr authorization_data)
{
--
2.34.1

View File

@ -0,0 +1,356 @@
From d3e073fa1cd314b344db1ec22f0add2702a6c299 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Feb 2022 14:33:22 -0500
Subject: [PATCH 2/4] common: Add API to reload settings from disk
Ideally we would reread /run/gdm/custom.conf after we've decided
graphics setup is complete. This is because the file may not
get written out by udev until after GDM is already started and waiting.
As a first step to get there, this commit adds an API for rereading
the file, and changes the SIGHUP handler to use it (instead of
the complete teardown and reinitialization it was doing before).
---
common/gdm-settings-direct.c | 9 +++++++++
common/gdm-settings-direct.h | 2 ++
common/gdm-settings.c | 14 ++++++++++++--
common/gdm-settings.h | 1 +
daemon/main.c | 12 ++----------
5 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/common/gdm-settings-direct.c b/common/gdm-settings-direct.c
index ddb31908..5fbe0326 100644
--- a/common/gdm-settings-direct.c
+++ b/common/gdm-settings-direct.c
@@ -224,35 +224,44 @@ hashify_list (GdmSettingsEntry *entry,
gboolean
gdm_settings_direct_init (GdmSettings *settings,
const char *file,
const char *root)
{
GSList *list;
g_return_val_if_fail (file != NULL, FALSE);
g_return_val_if_fail (root != NULL, FALSE);
g_debug ("Settings Direct Init");
if (schemas != NULL) {
g_hash_table_unref (schemas);
schemas = NULL;
}
if (! gdm_settings_parse_schemas (file, root, &list)) {
g_warning ("Unable to parse schemas");
return FALSE;
}
schemas = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)gdm_settings_entry_free);
g_slist_foreach (list, (GFunc)hashify_list, NULL);
settings_object = settings;
return TRUE;
}
+void
+gdm_settings_direct_reload (void)
+{
+ if (!settings_object)
+ return;
+
+ gdm_settings_reload (settings_object);
+}
+
void
gdm_settings_direct_shutdown (void)
{
}
diff --git a/common/gdm-settings-direct.h b/common/gdm-settings-direct.h
index 156489cd..6754955f 100644
--- a/common/gdm-settings-direct.h
+++ b/common/gdm-settings-direct.h
@@ -3,48 +3,50 @@
* 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.
*
*/
#ifndef __GDM_SETTINGS_DIRECT_H
#define __GDM_SETTINGS_DIRECT_H
#include <glib-object.h>
#include "gdm-settings.h"
G_BEGIN_DECLS
gboolean gdm_settings_direct_init (GdmSettings *settings,
const char *schemas_file,
const char *root);
+
+void gdm_settings_direct_reload (void);
void gdm_settings_direct_shutdown (void);
gboolean gdm_settings_direct_get (const char *key,
GValue *value);
gboolean gdm_settings_direct_set (const char *key,
GValue *value);
gboolean gdm_settings_direct_get_int (const char *key,
int *value);
gboolean gdm_settings_direct_get_uint (const char *key,
uint *value);
gboolean gdm_settings_direct_get_boolean (const char *key,
gboolean *value);
gboolean gdm_settings_direct_get_string (const char *key,
char **value);
G_END_DECLS
#endif /* __GDM_SETTINGS_DIRECT_H */
diff --git a/common/gdm-settings.c b/common/gdm-settings.c
index e6f46ec3..96c2f8d3 100644
--- a/common/gdm-settings.c
+++ b/common/gdm-settings.c
@@ -157,84 +157,94 @@ gdm_settings_class_init (GdmSettingsClass *klass)
object_class->finalize = gdm_settings_finalize;
signals [VALUE_CHANGED] =
g_signal_new ("value-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL,
NULL,
g_cclosure_marshal_generic,
G_TYPE_NONE,
3,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING);
}
static void
backend_value_changed (GdmSettingsBackend *backend,
const char *key,
const char *old_value,
const char *new_value,
GdmSettings *settings)
{
g_debug ("Emitting value-changed %s %s %s", key, old_value, new_value);
/* proxy it to internal listeners */
g_signal_emit (settings, signals [VALUE_CHANGED], 0, key, old_value, new_value);
}
-static void
-gdm_settings_init (GdmSettings *settings)
+void
+gdm_settings_reload (GdmSettings *settings)
{
GList *l;
GdmSettingsBackend *backend;
+ g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL);
+ g_list_free (settings->backends);
+ settings->backends = NULL;
+
backend = gdm_settings_desktop_backend_new (GDM_CUSTOM_CONF);
if (backend)
settings->backends = g_list_prepend (NULL, backend);
backend = gdm_settings_desktop_backend_new (GDM_RUNTIME_CONF);
if (backend)
settings->backends = g_list_prepend (settings->backends, backend);
for (l = settings->backends; l; l = g_list_next (l)) {
backend = l->data;
g_signal_connect (backend,
"value-changed",
G_CALLBACK (backend_value_changed),
settings);
}
}
+static void
+gdm_settings_init (GdmSettings *settings)
+{
+ gdm_settings_reload (settings);
+}
+
static void
gdm_settings_finalize (GObject *object)
{
GdmSettings *settings;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_SETTINGS (object));
settings = GDM_SETTINGS (object);
g_return_if_fail (settings != NULL);
g_list_foreach (settings->backends, (GFunc) g_object_unref, NULL);
g_list_free (settings->backends);
settings->backends = NULL;
settings_object = NULL;
G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object);
}
GdmSettings *
gdm_settings_new (void)
{
if (settings_object != NULL) {
g_object_ref (settings_object);
} else {
settings_object = g_object_new (GDM_TYPE_SETTINGS, NULL);
}
diff --git a/common/gdm-settings.h b/common/gdm-settings.h
index 786868a9..07b64785 100644
--- a/common/gdm-settings.h
+++ b/common/gdm-settings.h
@@ -13,45 +13,46 @@
* 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_SETTINGS_H
#define __GDM_SETTINGS_H
#include <glib-object.h>
G_BEGIN_DECLS
#define GDM_TYPE_SETTINGS (gdm_settings_get_type ())
G_DECLARE_FINAL_TYPE (GdmSettings, gdm_settings, GDM, SETTINGS, GObject)
typedef enum
{
GDM_SETTINGS_ERROR_GENERAL,
GDM_SETTINGS_ERROR_KEY_NOT_FOUND
} GdmSettingsError;
#define GDM_SETTINGS_ERROR gdm_settings_error_quark ()
GQuark gdm_settings_error_quark (void);
GdmSettings * gdm_settings_new (void);
+void gdm_settings_reload (GdmSettings *settings);
/* exported */
gboolean gdm_settings_get_value (GdmSettings *settings,
const char *key,
char **value,
GError **error);
gboolean gdm_settings_set_value (GdmSettings *settings,
const char *key,
const char *value,
GError **error);
G_END_DECLS
#endif /* __GDM_SETTINGS_H */
diff --git a/daemon/main.c b/daemon/main.c
index 1b893fe0..344d1b74 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -240,70 +240,62 @@ gdm_daemon_lookup_user (uid_t *uidp,
if G_UNLIKELY (gid == 0) {
gdm_fail (_("The GDM group should not be root. Aborting!"));
}
if (uidp != NULL) {
*uidp = uid;
}
if (gidp != NULL) {
*gidp = gid;
}
g_free (username);
g_free (groupname);
}
static gboolean
on_shutdown_signal_cb (gpointer user_data)
{
GMainLoop *mainloop = user_data;
g_main_loop_quit (mainloop);
return FALSE;
}
static gboolean
on_sighup_cb (gpointer user_data)
{
g_debug ("Got HUP signal");
- /* Reread config stuff like system config files, VPN service
- * files, etc
- */
- g_object_unref (settings);
- settings = gdm_settings_new ();
- if (settings != NULL) {
- if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
- g_warning ("Unable to initialize settings");
- }
- }
+
+ gdm_settings_reload (settings);
return TRUE;
}
static gboolean
is_debug_set (void)
{
gboolean debug;
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
return debug;
}
/* SIGUSR1 is used by the X server to tell us that we're ready, so
* block it. We'll unblock it in the worker thread in gdm-server.c
*/
static void
block_sigusr1 (void)
{
sigset_t mask;
sigemptyset (&mask);
sigaddset (&mask, SIGUSR1);
sigprocmask (SIG_BLOCK, &mask, NULL);
}
int
main (int argc,
char **argv)
{
GMainLoop *main_loop;
--
2.34.1

View File

@ -0,0 +1,109 @@
From b09ab8a73d5a4133f72846d529bbbfb7802ca535 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 6 Sep 2021 08:40:46 -0400
Subject: [PATCH 2/5] daemon: Don't update session type if no saved session
At the moment we always set the session type when the session name
is read. But users don't always have a session type specified.
If they don't, then don't set the session type.
https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/153
---
daemon/gdm-session.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 2b941e5e..b54687d5 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -995,73 +995,76 @@ worker_on_reauthenticated (GdmDBusWorker *worker,
static void
worker_on_saved_language_name_read (GdmDBusWorker *worker,
const char *language_name,
GdmSessionConversation *conversation)
{
GdmSession *self = conversation->session;
if (strlen (language_name) > 0) {
g_free (self->saved_language);
self->saved_language = g_strdup (language_name);
if (self->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_language_name_changed (self->greeter_interface,
language_name);
}
}
}
static void
worker_on_saved_session_name_read (GdmDBusWorker *worker,
const char *session_name,
GdmSessionConversation *conversation)
{
GdmSession *self = conversation->session;
if (! get_session_command_for_name (self, session_name, self->saved_session_type, NULL)) {
/* ignore sessions that don't exist */
g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name);
g_free (self->saved_session);
self->saved_session = NULL;
- } else if (strcmp (session_name,
- get_default_session_name (self)) != 0) {
- g_free (self->saved_session);
- self->saved_session = g_strdup (session_name);
-
- if (self->greeter_interface != NULL) {
- gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface,
- session_name);
+ update_session_type (self);
+ } else {
+ if (strcmp (session_name,
+ get_default_session_name (self)) != 0) {
+ g_free (self->saved_session);
+ self->saved_session = g_strdup (session_name);
+
+ if (self->greeter_interface != NULL) {
+ gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface,
+ session_name);
+ }
}
+ if (self->saved_session_type != NULL)
+ set_session_type (self, self->saved_session_type);
}
- update_session_type (self);
-
}
static void
worker_on_saved_session_type_read (GdmDBusWorker *worker,
const char *session_type,
GdmSessionConversation *conversation)
{
GdmSession *self = conversation->session;
g_free (self->saved_session_type);
self->saved_session_type = g_strdup (session_type);
}
static GdmSessionConversation *
find_conversation_by_pid (GdmSession *self,
GPid pid)
{
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, self->conversations);
while (g_hash_table_iter_next (&iter, &key, &value)) {
GdmSessionConversation *conversation;
conversation = (GdmSessionConversation *) value;
if (conversation->worker_pid == pid) {
return conversation;
}
}
--
2.34.1

View File

@ -0,0 +1,327 @@
From cc67c8de39358031fddc5ca7d8c993271d6606a7 Mon Sep 17 00:00:00 2001
From: Alan Coopersmith <alan.coopersmith@oracle.com>
Date: Thu, 7 Oct 2021 18:22:11 -0700
Subject: [PATCH 2/2] daemon: Support X servers built with -Dlisten_tcp=true
Xorg since version 1.17 doesn't listen to tcp sockets by default
unless it's explicitly built with -Dlisten_tcp=true.
GDM currently assumes X servers 1.17 and later are always built
without specifying -Dlisten_tcp=true and doesn't work properly
otherwise.
This commit enhances GDM to better handle these non-standard builds by
always passing '-nolisten tcp' on the command line when tcp should
be disabled, and likewise always passing '-listen tcp' on the command
line, assuming the X server is new enough to support it, when tcp
should be enabled.
Related #704
---
daemon/gdm-server.c | 21 +++++++++++----------
daemon/gdm-x-session.c | 12 ++++++------
meson.build | 4 ++--
3 files changed, 19 insertions(+), 18 deletions(-)
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 1ba00d45..e5d23521 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -290,72 +290,73 @@ gdm_server_resolve_command_line (GdmServer *server,
if (strcmp (arg, "-query") == 0 ||
strcmp (arg, "-indirect") == 0)
query_in_arglist = TRUE;
}
argv = g_renew (char *, argv, len + 12);
/* shift args down one */
for (i = len - 1; i >= 1; i--) {
argv[i+1] = argv[i];
}
/* server number is the FIRST argument, before any others */
argv[1] = g_strdup (server->display_name);
len++;
if (server->auth_file != NULL) {
argv[len++] = g_strdup ("-auth");
argv[len++] = g_strdup (server->auth_file);
}
if (server->display_seat_id != NULL) {
argv[len++] = g_strdup ("-seat");
argv[len++] = g_strdup (server->display_seat_id);
}
/* 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 (!server->disable_tcp && ! query_in_arglist) {
- argv[len++] = g_strdup ("-listen");
- argv[len++] = g_strdup ("tcp");
- }
-#else
- if (server->disable_tcp && ! query_in_arglist) {
- argv[len++] = g_strdup ("-nolisten");
- argv[len++] = g_strdup ("tcp");
- }
+ if (!query_in_arglist) {
+ if (server->disable_tcp) {
+ argv[len++] = g_strdup ("-nolisten");
+ argv[len++] = g_strdup ("tcp");
+ }
+#ifdef HAVE_XSERVER_WITH_LISTEN
+ if (!server->disable_tcp) {
+ argv[len++] = g_strdup ("-listen");
+ argv[len++] = g_strdup ("tcp");
+ }
#endif
+ }
if (vtarg != NULL && ! gotvtarg) {
argv[len++] = g_strdup (vtarg);
}
argv[len++] = NULL;
*argvp = argv;
*argcp = len;
return TRUE;
}
static void
rotate_logs (const char *path,
guint n_copies)
{
int i;
for (i = n_copies - 1; i > 0; i--) {
char *name_n;
char *name_n1;
name_n = g_strdup_printf ("%s.%d", path, i);
if (i > 1) {
name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
} else {
name_n1 = g_strdup (path);
}
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 5962da57..0b07ab5b 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -233,70 +233,70 @@ spawn_x_server (State *state,
if (g_getenv ("XDG_VTNR") != NULL) {
int vt;
vt = atoi (g_getenv ("XDG_VTNR"));
if (vt > 0 && vt < 64) {
vt_string = g_strdup_printf ("vt%d", vt);
}
}
display_fd_string = g_strdup_printf ("%d", DISPLAY_FILENO);
g_ptr_array_add (arguments, X_SERVER);
if (vt_string != NULL) {
g_ptr_array_add (arguments, vt_string);
}
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 doesn'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");
}
+
+#ifdef HAVE_XSERVER_WITH_LISTEN
+ if (allow_remote_connections) {
+ g_ptr_array_add (arguments, "-listen");
+ 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);
diff --git a/meson.build b/meson.build
index 52ac1941..02d609dc 100644
--- a/meson.build
+++ b/meson.build
@@ -44,61 +44,61 @@ glib_min_version = '2.56.0'
glib_dep = dependency('glib-2.0', version: '>=' + glib_min_version)
gobject_dep = dependency('gobject-2.0', version: '>=' + glib_min_version)
gio_dep = dependency('gio-2.0', version: '>=' + glib_min_version)
gio_unix_dep = dependency('gio-unix-2.0', version: '>=' + glib_min_version)
gtk_dep = dependency('gtk+-3.0', version: '>= 2.91.1')
libcanberra_gtk_dep = dependency('libcanberra-gtk3', version: '>= 0.4')
accountsservice_dep = dependency('accountsservice', version: '>= 0.6.35')
xcb_dep = dependency('xcb')
keyutils_dep = dependency('libkeyutils', required: false)
libselinux_dep = dependency('libselinux', required: get_option('selinux'))
# udev
if udev_dir == ''
if udev_dep.found()
udev_prefix = udev_dep.get_pkgconfig_variable('udevdir')
else
udev_prefix = gdm_prefix / 'lib' / 'udev'
endif
udev_dir = udev_prefix / 'rules.d'
endif
# X11
x_deps = declare_dependency(
dependencies: [
dependency('x11'),
dependency('xau'),
],
)
# Xserver 1.17 & later default to -nolisten and require -listen for remote access
xserver_deps = dependency('xorg-server', version : '>=1.17', required : false)
-xserver_nolisten_default = xserver_deps.found()
+xserver_has_listen = xserver_deps.found()
find_x_server_script = find_program('build-aux/find-x-server.sh', native: true)
find_x_server_out = run_command(find_x_server_script).stdout().strip()
if find_x_server_out != ''
x_bin = find_x_server_out
x_bin_path_split = x_bin.split('/')
i = 0
x_path = '/'
foreach dir : x_bin_path_split
if i < x_bin_path_split.length() - 1
x_path = x_path / dir
endif
i = i + 1
endforeach
else
# what to do, what to do, this is wrong, but this just sets the
# defaults, perhaps this user is cross compiling or some such
x_path = '/usr/bin/X11:/usr/X11R6/bin:/opt/X11R6/bin'
x_bin = '/usr/bin/X'
endif
xdmcp_dep = cc.find_library('Xdmcp', required: get_option('xdmcp'))
if xdmcp_dep.found() and get_option('tcp-wrappers')
libwrap_dep = cc.find_library('wrap')
endif
# systemd
systemd_dep = dependency('systemd')
libsystemd_dep = dependency('libsystemd')
if meson.version().version_compare('>= 0.53')
systemd_multiseat_x = find_program('systemd-multi-seat-x',
required: false,
dirs: [
@@ -200,61 +200,61 @@ conf.set_quoted('SYSCONFDIR', gdm_prefix / get_option('sysconfdir'))
conf.set_quoted('BINDIR', gdm_prefix / get_option('bindir'))
conf.set_quoted('LIBDIR', gdm_prefix / get_option('libdir'))
conf.set_quoted('LIBEXECDIR', gdm_prefix / get_option('libexecdir'))
conf.set_quoted('LOGDIR', get_option('log-dir'))
conf.set_quoted('DMCONFDIR', dmconfdir)
conf.set_quoted('GDMCONFDIR', gdmconfdir)
conf.set_quoted('GDM_SCREENSHOT_DIR', gdm_screenshot_dir)
conf.set_quoted('GDM_XAUTH_DIR', gdm_xauth_dir)
conf.set_quoted('GDM_RAN_ONCE_MARKER_DIR', ran_once_marker_dir)
conf.set_quoted('GDM_RUN_DIR', gdm_run_dir)
conf.set_quoted('GNOMELOCALEDIR', gdm_prefix / get_option('localedir'))
conf.set_quoted('AT_SPI_REGISTRYD_DIR', at_spi_registryd_dir)
conf.set_quoted('GDM_PID_FILE', gdm_pid_file)
conf.set_quoted('GNOME_SETTINGS_DAEMON_DIR', gnome_settings_daemon_dir)
conf.set_quoted('LANG_CONFIG_FILE', lang_config_file)
conf.set('HAVE_ADT', have_adt)
conf.set('HAVE_UTMP_H', have_utmp_header)
conf.set('HAVE_UTMPX_H', have_utmpx_header)
conf.set('HAVE_POSIX_GETPWNAM_R', have_posix_getpwnam_r)
conf.set('UTMP', utmp_struct)
conf.set('HAVE_GETUTXENT', cc.has_function('getutxent'))
conf.set('HAVE_UPDWTMP', cc.has_function('updwtmp'))
conf.set('HAVE_UPDWTMPX', cc.has_function('updwtmpx'))
conf.set('HAVE_LOGIN', cc.has_function('login', args: '-lutil'))
conf.set('HAVE_LOGOUT', cc.has_function('logout', args: '-lutil'))
conf.set('HAVE_LOGWTMP', cc.has_function('logwtmp', args: '-lutil'))
conf.set('HAVE_PAM_SYSLOG', have_pam_syslog)
conf.set('HAVE_KEYUTILS', keyutils_dep.found())
conf.set('SUPPORTS_PAM_EXTENSIONS', pam_extensions_supported)
conf.set('HAVE_SELINUX', libselinux_dep.found())
-conf.set('HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY', xserver_nolisten_default)
+conf.set('HAVE_XSERVER_WITH_LISTEN', xserver_has_listen)
conf.set('ENABLE_USER_DISPLAY_SERVER', get_option('user-display-server'))
conf.set('ENABLE_SYSTEMD_JOURNAL', get_option('systemd-journal'))
conf.set('ENABLE_WAYLAND_SUPPORT', get_option('wayland-support'))
conf.set('ENABLE_PROFILING', get_option('profiling'))
conf.set('GDM_INITIAL_VT', get_option('initial-vt'))
conf.set_quoted('GDM_DEFAULTS_CONF', gdm_defaults_conf)
conf.set_quoted('GDM_CUSTOM_CONF', gdm_custom_conf)
conf.set_quoted('GDM_RUNTIME_CONF', gdm_runtime_conf)
conf.set_quoted('GDM_SESSION_DEFAULT_PATH', get_option('default-path'))
conf.set_quoted('GDM_USERNAME', get_option('user'))
conf.set_quoted('GDM_GROUPNAME', get_option('group'))
conf.set('HAVE_LIBXDMCP', xdmcp_dep.found())
conf.set_quoted('SYSTEMD_X_SERVER', systemd_x_server)
conf.set('WITH_PLYMOUTH', plymouth_dep.found())
conf.set_quoted('X_SERVER', x_bin)
conf.set_quoted('X_PATH', x_path)
conf.set('HAVE_UT_UT_HOST', utmp_has_host_field)
conf.set('HAVE_UT_UT_PID', utmp_has_pid_field)
conf.set('HAVE_UT_UT_ID', utmp_has_id_field)
conf.set('HAVE_UT_UT_NAME', utmp_has_name_field)
conf.set('HAVE_UT_UT_TYPE', utmp_has_type_field)
conf.set('HAVE_UT_UT_EXIT_E_TERMINATION', utmp_has_exit_e_termination_field)
conf.set('HAVE_UT_UT_USER', utmp_has_user_field)
conf.set('HAVE_UT_UT_TIME', utmp_has_time_field)
conf.set('HAVE_UT_UT_TV', utmp_has_tv_field)
conf.set('HAVE_UT_UT_SYSLEN', utmp_has_syslen_field)
conf.set('ENABLE_IPV6', get_option('ipv6'))
configure_file(output: 'config.h', configuration: conf)
# Subdirs
--
2.34.1

View File

@ -0,0 +1,151 @@
From 618dfea6563d4f0bad0583b38b63746e44969d5e Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 5 Feb 2020 15:20:48 -0500
Subject: [PATCH 2/3] gdm-x-session: run session bus on non-seat0 seats
GNOME doesn't deal very well with multiple sessions
running on a multiple seats at the moment.
Until that's fixed, ensure sessions run on auxillary
seats get their own session bus.
---
daemon/gdm-session.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index a65fa0f9..f13b54af 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2864,119 +2864,128 @@ on_start_program_cb (GdmDBusWorker *worker,
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED) ||
g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
self = conversation->session;
service_name = conversation->service_name;
if (worked) {
self->session_pid = pid;
self->session_conversation = conversation;
g_debug ("GdmSession: Emitting 'session-started' signal with pid '%d'", pid);
g_signal_emit (self, signals[SESSION_STARTED], 0, service_name, pid);
} else {
gdm_session_stop_conversation (self, service_name);
g_debug ("GdmSession: Emitting 'session-start-failed' signal");
g_signal_emit (self, signals[SESSION_START_FAILED], 0, service_name, error->message);
}
}
void
gdm_session_start_session (GdmSession *self,
const char *service_name)
{
GdmSessionConversation *conversation;
GdmSessionDisplayMode display_mode;
gboolean is_x11 = TRUE;
gboolean run_launcher = FALSE;
gboolean allow_remote_connections = FALSE;
+ gboolean run_separate_bus = FALSE;
char *command;
char *program;
gboolean register_session;
g_return_if_fail (GDM_IS_SESSION (self));
g_return_if_fail (self->session_conversation == NULL);
conversation = find_conversation_by_name (self, service_name);
if (conversation == NULL) {
g_warning ("GdmSession: Tried to start session of "
"nonexistent conversation %s", service_name);
return;
}
stop_all_other_conversations (self, conversation, FALSE);
display_mode = gdm_session_get_display_mode (self);
#ifdef ENABLE_WAYLAND_SUPPORT
is_x11 = g_strcmp0 (self->session_type, "wayland") != 0;
#endif
if (display_mode == GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED ||
display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) {
run_launcher = TRUE;
}
register_session = !gdm_session_session_registers (self);
+ if (g_strcmp0 (self->display_seat_id, "seat0") != 0 && !run_launcher) {
+ run_separate_bus = TRUE;
+ }
+
if (self->selected_program == NULL) {
gboolean run_xsession_script;
command = get_session_command (self);
run_xsession_script = !gdm_session_bypasses_xsession (self);
if (self->display_is_local) {
gboolean disallow_tcp = TRUE;
gdm_settings_direct_get_boolean (GDM_KEY_DISALLOW_TCP, &disallow_tcp);
allow_remote_connections = !disallow_tcp;
} else {
allow_remote_connections = TRUE;
}
if (run_launcher) {
if (is_x11) {
program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"",
register_session ? "--register-session " : "",
run_xsession_script? "--run-script " : "",
allow_remote_connections? "--allow-remote-connections " : "",
command);
} else {
program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
register_session ? "--register-session " : "",
command);
}
} else if (run_xsession_script) {
- program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+ if (run_separate_bus) {
+ program = g_strdup_printf ("dbus-run-session -- " GDMCONFDIR "/Xsession \"%s\"", command);
+ } else {
+ program = g_strdup_printf (GDMCONFDIR "/Xsession \"%s\"", command);
+ }
} else {
program = g_strdup (command);
}
g_free (command);
} else {
/* FIXME:
* Always use a separate DBus bus for each greeter session.
* Firstly, this means that if we run multiple greeter session
* (which we really should not do, but have to currently), then
* each one will get its own DBus session bus.
* But, we also explicitly do this for seat0, because that way
* it cannot make use of systemd to run the GNOME session. This
* prevents the session lookup logic from getting confused.
* This has a similar effect as passing --builtin to gnome-session.
*
* We really should not be doing this. But the fix is to use
* separate dynamically created users and that requires some
* major refactorings.
*/
if (run_launcher) {
if (is_x11) {
program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"dbus-run-session -- %s\"",
register_session ? "--register-session " : "",
self->selected_program);
} else {
program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"dbus-run-session -- %s\"",
register_session ? "--register-session " : "",
self->selected_program);
}
--
2.32.0

View File

@ -0,0 +1,155 @@
From a9928bfcc9c6d81d60e047b7838d4107835b8f89 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Feb 2022 14:33:22 -0500
Subject: [PATCH 3/4] common: Reload settings when graphics initialize
If GDM starts faster than graphics initialize, then the
udev rules that write out /run/gdm/custom.conf might get
run too late for GDM to notice.
This commit changes GDM to reread its config after graphicals
initialization completes.
https://gitlab.gnome.org/GNOME/gdm/-/issues/763
---
daemon/gdm-local-display-factory.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 0b1d3482..8bca8ce9 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -1023,64 +1023,66 @@ on_seat_properties_changed (GDBusConnection *connection,
g_autoptr(GVariant) changed_prop = NULL;
g_autofree const gchar **invalidated_props = NULL;
gboolean changed = FALSE;
int ret;
/* Extract seat id, i.e. the last element of the object path. */
seat = strrchr (object_path, '/');
if (seat == NULL)
return;
seat += 1;
/* Valid seat IDs must start with seat, i.e. ignore "auto" */
if (!g_str_has_prefix (seat, "seat"))
return;
g_variant_get (parameters, "(s@a{sv}^a&s)", NULL, &changed_props, &invalidated_props);
changed_prop = g_variant_lookup_value (changed_props, "CanGraphical", NULL);
if (changed_prop)
changed = TRUE;
if (!changed && g_strv_contains (invalidated_props, "CanGraphical"))
changed = TRUE;
if (!changed)
return;
ret = sd_seat_can_graphical (seat);
if (ret < 0)
return;
- if (ret != 0)
+ if (ret != 0) {
+ gdm_settings_direct_reload ();
ensure_display_for_seat (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
- else
+ } else {
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
+ }
}
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
lookup_by_tty (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *tty_to_find = user_data;
g_autofree char *tty_to_check = NULL;
const char *session_id;
int ret;
session_id = gdm_display_get_session_id (display);
if (!session_id)
return FALSE;
ret = sd_session_get_tty (session_id, &tty_to_check);
@@ -1260,60 +1262,61 @@ on_vt_changed (GIOChannel *source,
}
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_CONTINUE;
}
#endif
#ifdef HAVE_UDEV
static void
on_uevent (GUdevClient *client,
const char *action,
GUdevDevice *device,
GdmLocalDisplayFactory *factory)
{
if (!g_udev_device_get_device_file (device))
return;
if (g_strcmp0 (action, "add") != 0 &&
g_strcmp0 (action, "change") != 0)
return;
if (!udev_is_settled (factory))
return;
g_signal_handler_disconnect (factory->gudev_client, factory->uevent_handler_id);
factory->uevent_handler_id = 0;
+ gdm_settings_direct_reload ();
ensure_display_for_seat (factory, "seat0");
}
#endif
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
const char *subsystems[] = { "drm", NULL };
factory->seat_new_id = g_dbus_connection_signal_subscribe (factory->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->seat_removed_id = g_dbus_connection_signal_subscribe (factory->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);
--
2.34.1

View File

@ -0,0 +1,87 @@
From 7084aea50bdc16ccecb4474ca79403429e79ec0e Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 29 Sep 2021 11:03:41 -0400
Subject: [PATCH 3/5] daemon: Infer session type from desktop file if user has
no saved session type
The accountsservice user cache file can specify a session type
associated with the saved session. This is optional though. If one
isn't specified GDM needs to figure out the session type based on the
list of preferred session types for the system and the session file
itself.
It was failing to do the latter, though. This commit fixes that.
---
daemon/gdm-session.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index b54687d5..a65fa0f9 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -1009,60 +1009,62 @@ worker_on_saved_language_name_read (GdmDBusWorker *worker,
}
}
}
static void
worker_on_saved_session_name_read (GdmDBusWorker *worker,
const char *session_name,
GdmSessionConversation *conversation)
{
GdmSession *self = conversation->session;
if (! get_session_command_for_name (self, session_name, self->saved_session_type, NULL)) {
/* ignore sessions that don't exist */
g_debug ("GdmSession: not using invalid .dmrc session: %s", session_name);
g_free (self->saved_session);
self->saved_session = NULL;
update_session_type (self);
} else {
if (strcmp (session_name,
get_default_session_name (self)) != 0) {
g_free (self->saved_session);
self->saved_session = g_strdup (session_name);
if (self->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface,
session_name);
}
}
if (self->saved_session_type != NULL)
set_session_type (self, self->saved_session_type);
+ else
+ update_session_type (self);
}
}
static void
worker_on_saved_session_type_read (GdmDBusWorker *worker,
const char *session_type,
GdmSessionConversation *conversation)
{
GdmSession *self = conversation->session;
g_free (self->saved_session_type);
self->saved_session_type = g_strdup (session_type);
}
static GdmSessionConversation *
find_conversation_by_pid (GdmSession *self,
GPid pid)
{
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, self->conversations);
while (g_hash_table_iter_next (&iter, &key, &value)) {
GdmSessionConversation *conversation;
conversation = (GdmSessionConversation *) value;
if (conversation->worker_pid == pid) {
return conversation;
--
2.34.1

View File

@ -0,0 +1,105 @@
From f30e557a8afcdfe5d571a625b4c99606315ed3b4 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 11 Feb 2019 10:32:55 -0500
Subject: [PATCH 3/3] session: ensure login screen over XDMCP connects to its
session
Right now GTK preferentially picks the wayland display over an
X11 display if it finds one.
That causes a problem for XDMCP sessions, since there may be a
wayland display running on the local console for the GDM user.
This commit addresses the issue by forcing the X11 backend if
the session is X11.
---
daemon/gdm-session.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index f13b54af..9f68166e 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2739,60 +2739,79 @@ set_up_session_environment (GdmSession *self)
}
static void
send_display_mode (GdmSession *self,
GdmSessionConversation *conversation)
{
GdmSessionDisplayMode mode;
mode = gdm_session_get_display_mode (self);
gdm_dbus_worker_call_set_session_display_mode (conversation->worker_proxy,
gdm_session_display_mode_to_string (mode),
conversation->worker_cancellable,
NULL, NULL);
}
static void
send_session_type (GdmSession *self,
GdmSessionConversation *conversation)
{
const char *session_type = "x11";
if (self->session_type != NULL) {
session_type = self->session_type;
}
gdm_dbus_worker_call_set_environment_variable (conversation->worker_proxy,
"XDG_SESSION_TYPE",
session_type,
conversation->worker_cancellable,
NULL, NULL);
+
+ /* If the session type is x11, then set GDK_BACKEND to x11 as well.
+ * This is so gnome-session-check-accelerated from an XDMCP connection doesn't
+ * try to use the wayland display running on the local console for the gdm
+ * user login screen session.
+ *
+ * That's the only case where we let a user log in more than once, so it's
+ * the only situation that matters.
+ *
+ * We can drop this code if we ever switch the login screen to use systemd's
+ * DynamicUser feature.
+ */
+ if (g_strcmp0 (session_type, "x11") == 0) {
+ gdm_dbus_worker_call_set_environment_variable (conversation->worker_proxy,
+ "GDK_BACKEND",
+ "x11",
+ conversation->worker_cancellable,
+ NULL, NULL);
+ }
}
void
gdm_session_open_session (GdmSession *self,
const char *service_name)
{
GdmSessionConversation *conversation;
g_return_if_fail (GDM_IS_SESSION (self));
conversation = find_conversation_by_name (self, service_name);
if (conversation != NULL) {
send_display_mode (self, conversation);
send_session_type (self, conversation);
gdm_dbus_worker_call_open (conversation->worker_proxy,
conversation->worker_cancellable,
(GAsyncReadyCallback) on_opened, conversation);
}
}
static void
stop_all_other_conversations (GdmSession *self,
GdmSessionConversation *conversation_to_keep,
gboolean now)
{
GHashTableIter iter;
gpointer key, value;
--
2.32.0

View File

@ -0,0 +1,559 @@
From d76d6ff0761d47df938f1dab0daeeecac2feb56e Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 6 Sep 2021 08:43:28 -0400
Subject: [PATCH 4/5] daemon: Consolidate session-type and
supported-session-types list
There's currently a bug in computing the session-type to use.
The `i > 0` check means wayland will overwrite x11 in the
transient session type list.
Morever, the separation between "session-type" and
"supported-session-types" is a little redundant. Since
supported-session-types is a sorted list, the first item should
always be the same as "session-type".
This commit addresses the bug and the redundant logic, by computing
the supported session types early in the function and indexing into
it to get the session-type.
A future cleanup could probably get rid of session-type entirely.
https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/153
---
daemon/gdm-local-display-factory.c | 193 +++++++++++++++++------------
1 file changed, 116 insertions(+), 77 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 141d64c6..eba38671 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -197,164 +197,226 @@ get_preferred_display_server (GdmLocalDisplayFactory *factory)
}
if (!wayland_enabled && !xorg_enabled) {
return g_strdup ("none");
}
gdm_settings_direct_get_string (GDM_KEY_PREFERRED_DISPLAY_SERVER, &preferred_display_server);
if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
if (wayland_enabled)
return g_strdup (preferred_display_server);
else
return g_strdup ("xorg");
}
if (g_strcmp0 (preferred_display_server, "xorg") == 0) {
if (xorg_enabled)
return g_strdup (preferred_display_server);
else
return g_strdup ("wayland");
}
if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) {
if (xorg_enabled)
return g_strdup (preferred_display_server);
}
return g_strdup ("none");
}
+struct GdmDisplayServerConfiguration {
+ const char *display_server;
+ const char *key;
+ const char *binary;
+ const char *session_type;
+} display_server_configuration[] = {
+#ifdef ENABLE_WAYLAND_SUPPORT
+ { "wayland", GDM_KEY_WAYLAND_ENABLE, "/usr/bin/Xwayland", "wayland" },
+#endif
+ { "xorg", GDM_KEY_XORG_ENABLE, "/usr/bin/Xorg", "x11" },
+ { NULL, NULL, NULL },
+};
+
+static gboolean
+display_server_enabled (GdmLocalDisplayFactory *factory,
+ const char *display_server)
+{
+ size_t i;
+
+ for (i = 0; display_server_configuration[i].display_server != NULL; i++) {
+ const char *key = display_server_configuration[i].key;
+ const char *binary = display_server_configuration[i].binary;
+ gboolean enabled = FALSE;
+
+ if (!g_str_equal (display_server_configuration[i].display_server,
+ display_server))
+ continue;
+
+ if (!gdm_settings_direct_get_boolean (key, &enabled) || !enabled)
+ return FALSE;
+
+ if (!g_file_test (binary, G_FILE_TEST_IS_EXECUTABLE))
+ return FALSE;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
static const char *
-gdm_local_display_factory_get_session_type (GdmLocalDisplayFactory *factory,
- gboolean should_fall_back)
+get_session_type_for_display_server (GdmLocalDisplayFactory *factory,
+ const char *display_server)
+{
+ size_t i;
+
+ for (i = 0; display_server_configuration[i].display_server != NULL; i++) {
+ if (!g_str_equal (display_server_configuration[i].display_server,
+ display_server))
+ continue;
+
+ return display_server_configuration[i].session_type;
+ }
+
+ return NULL;
+}
+
+static char **
+gdm_local_display_factory_get_session_types (GdmLocalDisplayFactory *factory,
+ gboolean should_fall_back)
{
- const char *session_types[3] = { NULL };
- gsize i, session_type_index = 0;
g_autofree gchar *preferred_display_server = NULL;
+ const char *fallback_display_server = NULL;
+ gboolean wayland_preferred = FALSE;
+ gboolean xorg_preferred = FALSE;
+ g_autoptr (GPtrArray) session_types_array = NULL;
+ char **session_types;
+
+ session_types_array = g_ptr_array_new ();
preferred_display_server = get_preferred_display_server (factory);
- if (g_strcmp0 (preferred_display_server, "wayland") != 0 &&
- g_strcmp0 (preferred_display_server, "xorg") != 0)
- return NULL;
+ g_debug ("GdmLocalDisplayFactory: Getting session type (prefers %s, falling back: %s)",
+ preferred_display_server, should_fall_back? "yes" : "no");
- for (i = 0; i < G_N_ELEMENTS (session_types) - 1; i++) {
-#ifdef ENABLE_WAYLAND_SUPPORT
- if (i > 0 ||
- g_strcmp0 (preferred_display_server, "wayland") == 0) {
- 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_types[i] = "wayland";
- continue;
- }
- }
- }
-#endif
+ wayland_preferred = g_str_equal (preferred_display_server, "wayland");
+ xorg_preferred = g_str_equal (preferred_display_server, "xorg");
+
+ if (wayland_preferred)
+ fallback_display_server = "xorg";
+ else if (xorg_preferred)
+ fallback_display_server = "wayland";
+ else
+ return NULL;
- if (i > 0 ||
- g_strcmp0 (preferred_display_server, "xorg") == 0) {
- gboolean xorg_enabled = FALSE;
- if (gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled)) {
- if (xorg_enabled && g_file_test ("/usr/bin/Xorg", G_FILE_TEST_IS_EXECUTABLE)) {
- session_types[i] = "x11";
- continue;
- }
- }
- }
+ if (!should_fall_back) {
+ if (display_server_enabled (factory, preferred_display_server))
+ g_ptr_array_add (session_types_array, (gpointer) get_session_type_for_display_server (factory, preferred_display_server));
}
- if (should_fall_back)
- session_type_index++;
+ if (display_server_enabled (factory, fallback_display_server))
+ g_ptr_array_add (session_types_array, (gpointer) get_session_type_for_display_server (factory, fallback_display_server));
- return session_types[session_type_index];
+ if (session_types_array->len == 0)
+ return NULL;
+
+ g_ptr_array_add (session_types_array, NULL);
+
+ session_types = g_strdupv ((char **) session_types_array->pdata);
+
+ return session_types;
}
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);
}
/*
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;
const char *session_type;
g_autofree gchar *preferred_display_server = NULL;
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
ret = FALSE;
g_debug ("GdmLocalDisplayFactory: Creating transient display");
preferred_display_server = get_preferred_display_server (factory);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
g_strcmp0 (preferred_display_server, "xorg") == 0) {
- session_type = gdm_local_display_factory_get_session_type (factory, FALSE);
+ g_auto(GStrv) session_types = NULL;
- if (session_type == NULL) {
+ session_types = gdm_local_display_factory_get_session_types (factory, FALSE);
+
+ if (session_types == NULL) {
g_set_error_literal (error,
GDM_DISPLAY_ERROR,
GDM_DISPLAY_ERROR_GENERAL,
"Both Wayland and Xorg are unavailable");
return FALSE;
}
display = gdm_local_display_new ();
- g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
+ g_object_set (G_OBJECT (display),
+ "session-type", session_types[0],
+ "supported-session-types", session_types,
+ NULL);
is_initial = TRUE;
}
#endif
if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0) {
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
}
if (display == NULL) {
g_set_error_literal (error,
GDM_DISPLAY_ERROR,
GDM_DISPLAY_ERROR_GENERAL,
"Invalid preferred display server configured");
return FALSE;
}
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)) {
@@ -549,243 +611,220 @@ lookup_prepared_display_by_seat_id (const char *id,
if (status != GDM_DISPLAY_PREPARED)
return FALSE;
return lookup_by_seat_id (id, display, user_data);
}
static int
on_seat0_graphics_check_timeout (gpointer user_data)
{
GdmLocalDisplayFactory *factory = user_data;
factory->seat0_graphics_check_timeout_id = 0;
/* Simply try to re-add seat0. If it is there already (i.e. CanGraphical
* turned TRUE, then we'll find it and it will not be created again).
*/
factory->seat0_graphics_check_timed_out = TRUE;
ensure_display_for_seat (factory, "seat0");
return G_SOURCE_REMOVE;
}
static void
ensure_display_for_seat (GdmLocalDisplayFactory *factory,
const char *seat_id)
{
int ret;
gboolean seat_supports_graphics;
gboolean is_seat0;
- const char *session_type = "wayland";
+ g_auto (GStrv) session_types = NULL;
+ const char *legacy_session_types[] = { "x11", NULL };
GdmDisplayStore *store;
GdmDisplay *display = NULL;
g_autofree char *login_session_id = NULL;
gboolean wayland_enabled = FALSE, xorg_enabled = FALSE;
g_autofree gchar *preferred_display_server = NULL;
- gboolean falling_back;
+ gboolean falling_back = FALSE;
gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled);
gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
preferred_display_server = get_preferred_display_server (factory);
if (g_strcmp0 (preferred_display_server, "none") == 0) {
g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
return;
}
ret = sd_seat_can_graphical (seat_id);
if (ret < 0) {
g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
return;
}
if (ret == 0) {
g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
seat_supports_graphics = FALSE;
} else {
g_debug ("GdmLocalDisplayFactory: System supports graphics");
seat_supports_graphics = TRUE;
}
if (g_strcmp0 (seat_id, "seat0") == 0) {
is_seat0 = TRUE;
falling_back = factory->num_failures > 0;
- session_type = gdm_local_display_factory_get_session_type (factory, falling_back);
+ session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
- session_type, falling_back? " fallback" : "");
+ session_types[0], falling_back? " fallback" : "");
} else {
is_seat0 = FALSE;
g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
/* Force legacy X11 for all auxiliary seats */
seat_supports_graphics = TRUE;
- session_type = "x11";
+ session_types = g_strdupv ((char **) legacy_session_types);
}
/* For seat0, we have a fallback logic to still try starting it after
* SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if
* CanGraphical is unset.
* This is ugly, but it means we'll come up eventually in some
* scenarios where no master device is present.
* Note that we'll force an X11 fallback even though there might be
* cases where an wayland capable device is present and simply not marked as
* master-of-seat. In these cases, this should likely be fixed in the
* udev rules.
*
* At the moment, systemd always sets CanGraphical for non-seat0 seats.
* This is because non-seat0 seats are defined by having master-of-seat
* set. This means we can avoid the fallback check for non-seat0 seats,
* which simplifies the code.
*/
if (is_seat0) {
if (!seat_supports_graphics) {
if (!factory->seat0_graphics_check_timed_out) {
if (factory->seat0_graphics_check_timeout_id == 0) {
g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT);
factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT,
on_seat0_graphics_check_timeout,
factory);
} else {
/* It is not yet time to force X11 fallback. */
g_debug ("GdmLocalDisplayFactory: seat0 display requested when there is no graphics support before graphics check timeout.");
}
return;
}
g_debug ("GdmLocalDisplayFactory: Assuming we can use seat0 for X11 even though system says it doesn't support graphics!");
g_debug ("GdmLocalDisplayFactory: This might indicate an issue where the framebuffer device is not tagged as master-of-seat in udev.");
seat_supports_graphics = TRUE;
- session_type = "x11";
wayland_enabled = FALSE;
+ g_strfreev (session_types);
+ session_types = g_strdupv ((char **) legacy_session_types);
} else {
g_clear_handle_id (&factory->seat0_graphics_check_timeout_id, g_source_remove);
}
}
if (!seat_supports_graphics)
return;
- if (session_type != NULL)
+ if (session_types != NULL)
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
- session_type, seat_id);
+ session_types[0], seat_id);
else if (g_strcmp0 (preferred_display_server, "legacy-xorg") == 0)
g_debug ("GdmLocalDisplayFactory: Legacy Xorg login display for seat %s requested",
seat_id);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
if (is_seat0)
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;
}
/* 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 ||
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->connection, seat_id, login_session_id);
return;
}
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
g_strcmp0 (preferred_display_server, "xorg") == 0) {
if (is_seat0) {
- g_autoptr (GPtrArray) supported_session_types = NULL;
-
- if (session_type == NULL) {
- g_warning ("GdmLocalDisplayFactory: Both Wayland and Xorg sessions are unavailable");
- return;
- }
-
- supported_session_types = g_ptr_array_new ();
-
- if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
- if (wayland_enabled)
- g_ptr_array_add (supported_session_types, "wayland");
- } else {
- if (xorg_enabled)
- g_ptr_array_add (supported_session_types, "x11");
- }
-
- if (!falling_back) {
- if (g_strcmp0 (preferred_display_server, "wayland") == 0) {
- if (xorg_enabled)
- g_ptr_array_add (supported_session_types, "x11");
- } else {
- if (wayland_enabled)
- g_ptr_array_add (supported_session_types, "wayland");
- }
- }
-
- g_ptr_array_add (supported_session_types, NULL);
-
display = gdm_local_display_new ();
- g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
- g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types->pdata, NULL);
+ g_object_set (G_OBJECT (display),
+ "session-type", session_types[0],
+ "supported-session-types", session_types,
+ NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
- const char *supported_session_types[] = { "x11", NULL };
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
- g_object_set (G_OBJECT (display), "supported-session-types", supported_session_types, NULL);
+ g_object_set (G_OBJECT (display),
+ "session-type", legacy_session_types[0],
+ "supported-session-types", legacy_session_types,
+ NULL);
}
g_object_set (display, "seat-id", seat_id, NULL);
g_object_set (display, "is-initial", is_seat0, NULL);
store_display (factory, display);
/* let store own the ref */
g_object_unref (display);
if (! gdm_display_manage (display)) {
gdm_display_unmanage (display);
}
return;
}
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
--
2.34.1

View File

@ -0,0 +1,163 @@
From 0131864b339dc0cc5f23def75e6caa5872c9ed11 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 7 Mar 2022 10:16:39 -0500
Subject: [PATCH 4/4] data: Use latest upstream udev rules
This pulls in the latest udev rule from upstream that gives us
wayland on nvidia when we can, and disables wayland on nvidia
when we should.
It also pulls in the latest handling for passthrough gpus.
---
data/61-gdm.rules.in | 139 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 135 insertions(+), 4 deletions(-)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index b1da191f..5dae00ea 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,6 +1,137 @@
+# identify virtio graphics cards to find passthrough setups
+SUBSYSTEM!="virtio", GOTO="gdm_virtio_device_end"
+ACTION!="add", GOTO="gdm_virtio_device_end"
+ATTR{vendor}=="0x1af4", ATTR{device}=="0x0010", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_virtio_device_end"
+LABEL="gdm_virtio_device_end"
+
+SUBSYSTEM!="pci", GOTO="gdm_pci_device_end"
+ACTION!="bind", ACTION!="add", GOTO="gdm_pci_device_end"
+
+# identify virtio graphics cards to find passthrough setups
+# cirrus
+ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end"
+# vga
+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end"
+# qxl
+ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-virtual-gpu", ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}="1", GOTO="gdm_pci_device_end"
+
# disable Wayland on Hi1710 chipsets
-ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
-# disable Wayland when using the proprietary nvidia driver
-DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", GOTO="gdm_disable_wayland"
+
+# disable Wayland on Matrox chipsets
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", GOTO="gdm_disable_wayland"
+
+# disable Wayland on aspeed chipsets
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", GOTO="gdm_disable_wayland"
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", GOTO="gdm_disable_wayland"
+
+LABEL="gdm_pci_device_end"
+
# disable Wayland if modesetting is disabled
-IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+KERNEL!="card[0-9]*", GOTO="gdm_nomodeset_end"
+SUBSYSTEM!="drm", GOTO="gdm_nomodeset_end"
+IMPORT{parent}="GDM_MACHINE_HAS_VIRTUAL_GPU"
+ENV{GDM_MACHINE_HAS_VIRTUAL_GPU}!="1", RUN+="/usr/bin/touch /run/udev/gdm-machine-has-hardware-gpu"
+# but keep it enabled for simple framebuffer drivers
+DRIVERS=="simple-framebuffer", GOTO="gdm_nomodeset_end"
+IMPORT{cmdline}="nomodeset", GOTO="gdm_disable_wayland"
+LABEL="gdm_nomodeset_end"
+
+# The vendor nvidia driver has multiple modules that need to be loaded before GDM can make an
+# informed choice on which way to proceed, so force GDM to wait until NVidia's modules are
+# loaded before starting up.
+KERNEL!="nvidia", GOTO="gdm_nvidia_end"
+SUBSYSTEM!="module", GOTO="gdm_nvidia_end"
+ACTION!="add", GOTO="gdm_nvidia_end"
+RUN+="/usr/bin/touch /run/udev/gdm-machine-has-vendor-nvidia-driver"
+
+# Check if suspend/resume services necessary for working wayland support is available
+TEST{0711}!="/usr/bin/nvidia-sleep.sh", GOTO="gdm_disable_wayland"
+TEST{0711}!="/usr/lib/systemd/system-sleep/nvidia", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c \"sed -e 's/: /=/g' -e 's/\([^[:upper:]]\)\([[:upper:]]\)/\1_\2/g' -e 's/[[:lower:]]/\U&/g' -e 's/^/NVIDIA_/' /proc/driver/nvidia/params\""
+ENV{NVIDIA_PRESERVE_VIDEO_MEMORY_ALLOCATIONS}!="1", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c 'echo NVIDIA_HIBERNATE=`systemctl is-enabled nvidia-hibernate`'"
+ENV{NVIDIA_HIBERNATE}!="enabled", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c 'echo NVIDIA_RESUME=`systemctl is-enabled nvidia-resume`'"
+ENV{NVIDIA_RESUME}!="enabled", GOTO="gdm_disable_wayland"
+IMPORT{program}="/bin/sh -c 'echo NVIDIA_SUSPEND=`systemctl is-enabled nvidia-suspend`'"
+ENV{NVIDIA_SUSPEND}!="enabled", GOTO="gdm_disable_wayland"
+LABEL="gdm_nvidia_end"
+
+# If this machine has an internal panel, take note, since it's probably a laptop
+# FIXME: It could be "ghost connectors" make this pop positive for some workstations
+# in the wild. If so, we may have to fallback to looking at the chassis type from
+# dmi data or acpi
+KERNEL!="card[0-9]-eDP-*", GOTO="gdm_laptop_check_end"
+SUBSYSTEM!="drm", GOTO="gdm_laptop_check_end"
+ACTION!="add", GOTO="gdm_laptop_check_end"
+RUN+="/usr/bin/touch /run/udev/gdm-machine-is-laptop"
+GOTO="gdm_hybrid_nvidia_laptop_check"
+LABEL="gdm_laptop_check_end"
+
+# If this is a hybrid graphics setup, take note
+KERNEL!="card[1-9]*", GOTO="gdm_hybrid_graphics_check_end"
+KERNEL=="card[1-9]-*", GOTO="gdm_hybrid_graphics_check_end"
+SUBSYSTEM!="drm", GOTO="gdm_hybrid_graphics_check_end"
+ACTION!="add", GOTO="gdm_hybrid_graphics_check_end"
+RUN+="/usr/bin/touch /run/udev/gdm-machine-has-hybrid-graphics"
+LABEL="gdm_hybrid_graphics_check_end"
+
+# If this is a hybrid graphics laptop with vendor nvidia driver, disable wayland
+LABEL="gdm_hybrid_nvidia_laptop_check"
+TEST!="/run/udev/gdm-machine-is-laptop", GOTO="gdm_hybrid_nvidia_laptop_check_end"
+TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_hybrid_nvidia_laptop_check_end"
+TEST!="/run/udev/gdm-machine-has-vendor-nvidia-driver", GOTO="gdm_hybrid_nvidia_laptop_check_end"
+GOTO="gdm_disable_wayland"
+LABEL="gdm_hybrid_nvidia_laptop_check_end"
+
+# Disable wayland in situation where we're in a guest with a virtual gpu and host passthrough gpu
+LABEL="gdm_virt_passthrough_check"
+TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_virt_passthrough_check_end"
+TEST!="/run/udev/gdm-machine-has-virtual-gpu", GOTO="gdm_virt_passthrough_check_end"
+TEST!="/run/udev/gdm-machine-has-hardware-gpu", GOTO="gdm_virt_passthrough_check_end"
+GOTO="gdm_disable_wayland"
+LABEL="gdm_virt_passthrough_check_end"
+
+# Disable wayland when there are multiple virtual gpus
+LABEL="gdm_virt_multi_gpu_check"
+TEST!="/run/udev/gdm-machine-has-hybrid-graphics", GOTO="gdm_virt_multi_gpu_check_end"
+TEST!="/run/udev/gdm-machine-has-virtual-gpu", GOTO="gdm_virt_multi_gpu_check_end"
+TEST=="/run/udev/gdm-machine-has-hardware-gpu", GOTO="gdm_virt_multi_gpu_check_end"
+LABEL="gdm_virt_multi_gpu_check_end"
+
+# Disable wayland when nvidia modeset is disabled or when drivers are a lower
+# version than 470,
+# For versions above 470 but lower than 510 prefer Xorg,
+# Above 510, prefer Wayland.
+KERNEL!="nvidia_drm", GOTO="gdm_nvidia_drm_end"
+SUBSYSTEM!="module", GOTO="gdm_nvidia_drm_end"
+ACTION!="add", GOTO="gdm_nvidia_drm_end"
+# disable wayland if nvidia-drm modeset is not enabled
+ATTR{parameters/modeset}!="Y", GOTO="gdm_disable_wayland"
+# disable wayland for nvidia drivers versions lower than 470
+ATTR{version}=="4[0-6][0-9].*|[0-3][0-9][0-9].*|[0-9][0-9].*|[0-9].*", GOTO="gdm_disable_wayland"
+# For nvidia drivers versions Above 510, keep Wayland by default
+ATTR{version}=="[5-9][1-9][0-9].*", GOTO="gdm_end"
+# For nvidia drivers versions 470-495, prefer Xorg by default
+GOTO="gdm_prefer_xorg"
+LABEL="gdm_nvidia_drm_end"
+
+GOTO="gdm_end"
+
+LABEL="gdm_prefer_xorg"
+RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg"
+GOTO="gdm_end"
+
+LABEL="gdm_disable_wayland"
+RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+GOTO="gdm_end"
+
+LABEL="gdm_end"
--
2.34.1

View File

@ -0,0 +1,96 @@
From 0e467e3fb32d9e2a7499069699527638eb2c2be1 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 7 Oct 2021 15:34:27 -0400
Subject: [PATCH 5/5] local-display-factory: Don't crash if Xorg and Wayland
are both unavailable
At the moment if Wayland doesn't work, the login screen will fall back
to Xorg, and if Xorg doesn't work the login screen will fall back to
Wayland.
But if the fall back choice is disabled explicitly, GDM will just crash.
This commit fixes the crash.
Closes: https://gitlab.gnome.org/GNOME/gdm/-/issues/739
---
daemon/gdm-local-display-factory.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index eba38671..120847f9 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -651,62 +651,67 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
gdm_settings_direct_get_boolean (GDM_KEY_XORG_ENABLE, &xorg_enabled);
preferred_display_server = get_preferred_display_server (factory);
if (g_strcmp0 (preferred_display_server, "none") == 0) {
g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
return;
}
ret = sd_seat_can_graphical (seat_id);
if (ret < 0) {
g_critical ("Failed to query CanGraphical information for seat %s", seat_id);
return;
}
if (ret == 0) {
g_debug ("GdmLocalDisplayFactory: System doesn't currently support graphics");
seat_supports_graphics = FALSE;
} else {
g_debug ("GdmLocalDisplayFactory: System supports graphics");
seat_supports_graphics = TRUE;
}
if (g_strcmp0 (seat_id, "seat0") == 0) {
is_seat0 = TRUE;
falling_back = factory->num_failures > 0;
session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
- g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
- session_types[0], falling_back? " fallback" : "");
+ if (session_types == NULL) {
+ g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
+ seat_supports_graphics = FALSE;
+ } else {
+ g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
+ session_types[0], falling_back? " fallback" : "");
+ }
} else {
is_seat0 = FALSE;
g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
/* Force legacy X11 for all auxiliary seats */
seat_supports_graphics = TRUE;
session_types = g_strdupv ((char **) legacy_session_types);
}
/* For seat0, we have a fallback logic to still try starting it after
* SEAT0_GRAPHICS_CHECK_TIMEOUT seconds. i.e. we simply continue even if
* CanGraphical is unset.
* This is ugly, but it means we'll come up eventually in some
* scenarios where no master device is present.
* Note that we'll force an X11 fallback even though there might be
* cases where an wayland capable device is present and simply not marked as
* master-of-seat. In these cases, this should likely be fixed in the
* udev rules.
*
* At the moment, systemd always sets CanGraphical for non-seat0 seats.
* This is because non-seat0 seats are defined by having master-of-seat
* set. This means we can avoid the fallback check for non-seat0 seats,
* which simplifies the code.
*/
if (is_seat0) {
if (!seat_supports_graphics) {
if (!factory->seat0_graphics_check_timed_out) {
if (factory->seat0_graphics_check_timeout_id == 0) {
g_debug ("GdmLocalDisplayFactory: seat0 doesn't yet support graphics. Waiting %d seconds to try again.", SEAT0_GRAPHICS_CHECK_TIMEOUT);
factory->seat0_graphics_check_timeout_id = g_timeout_add_seconds (SEAT0_GRAPHICS_CHECK_TIMEOUT,
--
2.34.1

View File

@ -0,0 +1,9 @@
load-module module-device-restore
load-module module-card-restore
load-module module-udev-detect
load-module module-native-protocol-unix
load-module module-default-device-restore
load-module module-always-sink
load-module module-intended-roles
load-module module-suspend-on-idle
load-module module-position-event-sounds

View File

@ -0,0 +1,3 @@
[org.gnome.login-screen]
logo='/usr/share/pixmaps/fedora-gdm-logo.png'
enable-smartcard-authentication=false

3294
SPECS/gdm.spec Normal file

File diff suppressed because it is too large Load Diff