import gdm-40.0-15.el8

This commit is contained in:
CentOS Sources 2021-11-09 05:00:59 -05:00 committed by Stepan Oksanichenko
parent 9f0b1f2881
commit 7de8cc966a
94 changed files with 5098 additions and 18828 deletions

View File

@ -1 +1 @@
3c619c91941b2df0362a67b905669f8852106bf5 SOURCES/gdm-3.28.3.tar.xz
05c48de8765bde97768b6740417ad6c374c20763 SOURCES/gdm-40.0.tar.xz

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/gdm-3.28.3.tar.xz
SOURCES/gdm-40.0.tar.xz

View File

@ -1,4 +1,4 @@
From fa5733788ae5f8e8caeb07e956be370e96f9b6b1 Mon Sep 17 00:00:00 2001
From a447cd87b99868348ecf69479eb7958f20a318a2 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
@ -14,30 +14,45 @@ that but more might be added in the future.
https://bugzilla.gnome.org/show_bug.cgi?id=777708
---
daemon/Makefile.am | 1 +
daemon/gdm-display.c | 29 +++++++++++++++++++++++++++++
2 files changed, 30 insertions(+)
1 file changed, 29 insertions(+)
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index ab5dda0..786e0c5 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -14,6 +14,7 @@ AM_CPPFLAGS = \
-DLOCALSTATEDIR=\"$(localstatedir)\" \
-DLOGDIR=\"$(logdir)\" \
-DSBINDIR=\"$(sbindir)\" \
+ -DSYSCONFDIR=\"$(sysconfdir)\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \
-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 0057e2c..2af8e13 100644
index 687e7da4b..b3bdf066d 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -1456,6 +1456,31 @@ can_create_environment (const char *session_id)
@@ -1591,103 +1591,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
+static gboolean
+initial_setup_disabled_by_anaconda (void)
+{
+ GKeyFile *key_file;
@ -62,11 +77,46 @@ index 0057e2c..2af8e13 100644
+ return disabled;
+}
+
+static gboolean
static gboolean
wants_initial_setup (GdmDisplay *self)
{
GdmDisplayPrivate *priv;
gboolean enabled = FALSE;
@@ -1480,6 +1505,10 @@ wants_initial_setup (GdmDisplay *self)
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;
}
@ -77,6 +127,33 @@ index 0057e2c..2af8e13 100644
return enabled;
}
--
2.9.3
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.28.0

View File

@ -0,0 +1,241 @@
From 85951a0384cb7f37d99669575fad4aea155f25a8 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 5 May 2021 10:50:56 -0400
Subject: [PATCH 1/5] Revert "gdm-{wayland,x}-session: don't overwrite user env
with fallback vars"
This reverts commit ccecd9c975d04da80db4cd547b67a1a94fa83292.
---
daemon/gdm-wayland-session.c | 22 +---------------------
daemon/gdm-x-session.c | 22 +---------------------
2 files changed, 2 insertions(+), 42 deletions(-)
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
index d0404d2c1..35679b194 100644
--- a/daemon/gdm-wayland-session.c
+++ b/daemon/gdm-wayland-session.c
@@ -262,112 +262,92 @@ on_session_finished (GSubprocess *subprocess,
state->session_exit_status = exit_status;
} else {
int signal_number;
signal_number = g_subprocess_get_term_sig (subprocess);
g_debug ("session was killed with status %d", signal_number);
}
g_clear_object (&state->session_subprocess);
out:
g_main_loop_quit (state->main_loop);
}
static gboolean
spawn_session (State *state,
GCancellable *cancellable)
{
GSubprocessLauncher *launcher = NULL;
GSubprocess *subprocess = NULL;
GError *error = NULL;
gboolean is_running = FALSE;
int ret;
char **argv = NULL;
static const char *session_variables[] = { "DISPLAY",
"XAUTHORITY",
"WAYLAND_DISPLAY",
"WAYLAND_SOCKET",
"GNOME_SHELL_SESSION_MODE",
NULL };
- /* The environment variables listed below are those we have set (or
- * received from our own execution environment) only as a fallback to
- * make things work, as opposed to a information directly pertaining to
- * the session about to be started. Variables listed here will not
- * overwrite the existing environment (possibly) imported from the
- * systemd --user instance.
- * As an example: We need a PATH for some of the launched subprocesses
- * to work, but if the user (or the distributor) has customized the PATH
- * via one of systemds user-environment-generators, that version should
- * be preferred. */
- static const char *fallback_variables[] = { "PATH", NULL };
g_debug ("Running wayland session");
ret = g_shell_parse_argv (state->session_command,
NULL,
&argv,
&error);
if (!ret) {
g_debug ("could not parse session arguments: %s", error->message);
goto out;
}
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
if (state->environment != NULL) {
size_t i;
for (i = 0; state->environment[i] != NULL; i++) {
g_auto(GStrv) environment_entry = NULL;
if (state->environment[i][0] == '\0') {
continue;
}
environment_entry = g_strsplit (state->environment[i], "=", 2);
if (environment_entry[0] == NULL || environment_entry[1] == NULL) {
continue;
}
- /* Merge the environment block imported from systemd --user with the
- * environment we have set for ourselves (and thus pass on to the
- * launcher process). Variables we have set have precedence, as to not
- * import stale data from prior user sessions, with the exception of
- * those listed in fallback_variables. See the comment there for more
- * explanations. */
- g_subprocess_launcher_setenv (launcher,
- environment_entry[0],
- environment_entry[1],
- g_strv_contains (fallback_variables, environment_entry[0]));
+ g_subprocess_launcher_setenv (launcher, environment_entry[0], environment_entry[1], FALSE);
}
/* Don't allow session specific environment variables from earlier sessions to
* leak through */
for (i = 0; session_variables[i] != NULL; i++) {
if (g_getenv (session_variables[i]) == NULL) {
g_subprocess_launcher_unsetenv (launcher, session_variables[i]);
}
}
}
if (state->bus_address != NULL) {
g_subprocess_launcher_setenv (launcher, "DBUS_SESSION_BUS_ADDRESS", state->bus_address, TRUE);
}
subprocess = g_subprocess_launcher_spawnv (launcher,
(const char * const *) argv,
&error);
g_strfreev (argv);
if (subprocess == NULL) {
g_debug ("could not start session: %s", error->message);
goto out;
}
state->session_subprocess = g_object_ref (subprocess);
g_subprocess_wait_async (state->session_subprocess,
cancellable,
(GAsyncReadyCallback)
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 5962da572..b15483614 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -588,102 +588,82 @@ on_session_finished (GSubprocess *subprocess,
state->session_exit_status = exit_status;
} else {
int signal_number;
signal_number = g_subprocess_get_term_sig (subprocess);
g_debug ("session was killed with status %d", signal_number);
}
g_clear_object (&state->session_subprocess);
out:
g_main_loop_quit (state->main_loop);
}
static gboolean
spawn_session (State *state,
gboolean run_script,
GCancellable *cancellable)
{
GSubprocessLauncher *launcher = NULL;
GSubprocess *subprocess = NULL;
GError *error = NULL;
gboolean is_running = FALSE;
const char *vt;
static const char *session_variables[] = { "DISPLAY",
"XAUTHORITY",
"WAYLAND_DISPLAY",
"WAYLAND_SOCKET",
"GNOME_SHELL_SESSION_MODE",
NULL };
- /* The environment variables listed below are those we have set (or
- * received from our own execution environment) only as a fallback to
- * make things work, as opposed to a information directly pertaining to
- * the session about to be started. Variables listed here will not
- * overwrite the existing environment (possibly) imported from the
- * systemd --user instance.
- * As an example: We need a PATH for some of the launched subprocesses
- * to work, but if the user (or the distributor) has customized the PATH
- * via one of systemds user-environment-generators, that version should
- * be preferred. */
- static const char *fallback_variables[] = { "PATH", NULL };
g_debug ("Running X session");
launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
if (state->environment != NULL) {
size_t i;
for (i = 0; state->environment[i] != NULL; i++) {
g_auto(GStrv) environment_entry = NULL;
if (state->environment[i][0] == '\0') {
continue;
}
environment_entry = g_strsplit (state->environment[i], "=", 2);
if (environment_entry[0] == NULL || environment_entry[1] == NULL) {
continue;
}
- /* Merge the environment block imported from systemd --user with the
- * environment we have set for ourselves (and thus pass on to the
- * launcher process). Variables we have set have precedence, as to not
- * import stale data from prior user sessions, with the exception of
- * those listed in fallback_variables. See the comment there for more
- * explanations. */
- g_subprocess_launcher_setenv (launcher,
- environment_entry[0],
- environment_entry[1],
- g_strv_contains (fallback_variables, environment_entry[0]));
+ g_subprocess_launcher_setenv (launcher, environment_entry[0], environment_entry[1], FALSE);
}
/* Don't allow session specific environment variables from earlier sessions to
* leak through */
for (i = 0; session_variables[i] != NULL; i++) {
if (g_getenv (session_variables[i]) == NULL) {
g_subprocess_launcher_unsetenv (launcher, session_variables[i]);
}
}
}
g_subprocess_launcher_setenv (launcher, "DISPLAY", state->display_name, TRUE);
g_subprocess_launcher_setenv (launcher, "XAUTHORITY", state->auth_file, TRUE);
if (state->bus_address != NULL) {
g_subprocess_launcher_setenv (launcher, "DBUS_SESSION_BUS_ADDRESS", state->bus_address, TRUE);
}
vt = g_getenv ("XDG_VTNR");
if (vt != NULL) {
g_subprocess_launcher_setenv (launcher, "WINDOWPATH", vt, TRUE);
}
if (run_script) {
subprocess = g_subprocess_launcher_spawn (launcher,
&error,
GDMCONFDIR "/Xsession",
state->session_command,
NULL);
--
2.30.1

View File

@ -1,135 +0,0 @@
From b9f38b65417923624bf97a18daf1c2ede5e8651e Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sun, 15 Dec 2019 14:51:44 -0500
Subject: [PATCH] daemon: fix wayland detection when deciding to bypass
Xsession
At the moment if there's a session file with the same name in
both /usr/share/xsessions and /usr/share/wayland-sessions, GDM
will think the wayland is getting used when deciding whether or
not to bypass the /etc/gdm/Xsession script, even if wayland is
explicitly being ignored.
This commit fixes the check.
---
daemon/gdm-session.c | 28 ++++++++++++++--------------
1 file changed, 14 insertions(+), 14 deletions(-)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index a8263ba11..ecb2b3cac 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -3145,96 +3145,96 @@ gdm_session_get_session_id (GdmSession *self)
return conversation->session_id;
}
const char *
gdm_session_get_conversation_session_id (GdmSession *self,
const char *service_name)
{
GdmSessionConversation *conversation;
g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
conversation = find_conversation_by_name (self, service_name);
if (conversation == NULL) {
return NULL;
}
return conversation->session_id;
}
static char *
get_session_filename (GdmSession *self)
{
return g_strdup_printf ("%s.desktop", get_session_name (self));
}
#ifdef ENABLE_WAYLAND_SUPPORT
static gboolean
gdm_session_is_wayland_session (GdmSession *self)
{
- GKeyFile *key_file;
+ g_autoptr (GKeyFile) key_file = NULL;
gboolean is_wayland_session = FALSE;
- char *filename;
- char *full_path = NULL;
+ g_autofree char *filename = NULL;
+ g_autofree char *full_path = NULL;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
filename = get_session_filename (self);
- key_file = load_key_file_for_file (self, filename, "wayland", &full_path);
+ if (!self->priv->ignore_wayland) {
+ key_file = load_key_file_for_file (self, filename, "wayland", &full_path);
- if (key_file == NULL) {
- goto out;
- }
+ if (key_file == NULL) {
+ goto out;
+ }
- if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
- is_wayland_session = TRUE;
+ if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
+ is_wayland_session = TRUE;
+ }
}
- g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
out:
- g_clear_pointer (&key_file, (GDestroyNotify) g_key_file_free);
- g_free (filename);
+ g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
+
return is_wayland_session;
}
#endif
static void
update_session_type (GdmSession *self)
{
#ifdef ENABLE_WAYLAND_SUPPORT
gboolean is_wayland_session = FALSE;
- if (!self->priv->ignore_wayland)
- is_wayland_session = gdm_session_is_wayland_session (self);
+ is_wayland_session = gdm_session_is_wayland_session (self);
if (is_wayland_session) {
set_session_type (self, "wayland");
} else {
set_session_type (self, NULL);
}
#endif
}
gboolean
gdm_session_bypasses_xsession (GdmSession *self)
{
GError *error;
GKeyFile *key_file;
gboolean res;
gboolean bypasses_xsession = FALSE;
char *filename = NULL;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
#ifdef ENABLE_WAYLAND_SUPPORT
if (gdm_session_is_wayland_session (self)) {
bypasses_xsession = TRUE;
goto out;
}
#endif
filename = get_session_filename (self);
--
2.18.1

View File

@ -0,0 +1,103 @@
From cebcf2a4d29f01061dedf8714db2842b9582900c 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 1/3] 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 23e2d7f9f..cbd6a6a21 100644
--- a/data/meson.build
+++ b/data/meson.build
@@ -131,60 +131,70 @@ pam_data_files_map = {
'arch': [
'gdm-autologin',
'gdm-launch-environment',
'gdm-fingerprint',
'gdm-smartcard',
'gdm-password',
'gdm-pin',
],
'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 000000000..09544f11e
--- /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.30.1

View File

@ -1,7 +1,7 @@
From 53c549876bcb7363d1d6dca70f2e1d3889741a06 Mon Sep 17 00:00:00 2001
From 8c9fe8ebd9e584adaec0a80ee4c4eaf5357422a5 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
Subject: [PATCH 1/2] data: add system dconf databases to gdm profile
This way system settings can affect the login screen.
---
@ -9,7 +9,7 @@ This way system settings can affect the login screen.
1 file changed, 4 insertions(+)
diff --git a/data/dconf/gdm.in b/data/dconf/gdm.in
index 4d8bf1748..606e0b863 100644
index 4d8bf1748..9694078fb 100644
--- a/data/dconf/gdm.in
+++ b/data/dconf/gdm.in
@@ -1,2 +1,6 @@
@ -20,5 +20,5 @@ index 4d8bf1748..606e0b863 100644
+system-db:distro
file-db:@DATADIR@/@PACKAGE@/greeter-dconf-defaults
--
2.26.0
2.30.1

View File

@ -1,28 +0,0 @@
From f2ac0603854c7933ecea4a13876fa7e72fd66d1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Thu, 6 Sep 2018 10:14:08 -0400
Subject: [PATCH] data: disable wayland for proprietary nvidia machines
At the moment GLX applications don't work well when the
proprietary nvidia driver is used with a wayland session.
For now, disable wayland on that hardware, and users who
want to opt in can just edit the udev rule.
(or add their own that overrides it)
---
data/61-gdm.rules.in | 3 +++
1 file changed, 3 insertions(+)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index de8e17903..26cf9cf51 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,2 +1,5 @@
# disable Wayland on Cirrus chipsets
ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland when using the proprietary nvidia driver
+DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland"
--
2.20.1

View File

@ -0,0 +1,63 @@
From e01c0894669f5fe3d1a1c4148b7507e61b95d035 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 11 Feb 2019 18:14:07 -0500
Subject: [PATCH] data: disable wayland on certain hardware
We're having issues with wayland on passthrough to virt
setups and with the vendor nvidia driver on hybrid graphics
setups, so disable it in those cases.
Also disable it on server chips for performance reasons.
---
data/61-gdm.rules.in | 39 +++++++++++++++++++++++++++++++++++----
1 file changed, 35 insertions(+), 4 deletions(-)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index b1da191f..d599a146 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,6 +1,37 @@
# 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", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland on Matrox chipsets
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland on aspeed chipsets
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland on hybrid systems with vendor nvidia driver
+# default to Xorg on single gpu vendor nvidia systems
+DRIVER=="nvidia", ENV{GDM_HAS_VENDOR_NVIDIA_DRIVER}="1"
+DRIVER=="nvidia", RUN+="@libexecdir@/gdm-runtime-config set daemon PreferredDisplayServer xorg"
+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_NVIDIA_DRIVER}=="1", RUN+="@libexecdir@/gdm-disable-wayland"
+ACTION=="add", SUBSYSTEM=="module", KERNEL=="nvidia_drm", ATTR{parameters/modeset}=="N", RUN+="/usr/libexec/gdm-disable-wayland"
+
+# disable Wayland on HyperV guests
+DRIVER=="hyperv_fb", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland on passthrough graphics setups for now (assumes passthrough if
+# there is more than one card, and one of the cards is virt: cirrus, bochs, qxl)
+ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+
+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_VIRTUAL_GPU}=="1", RUN+="@libexecdir@/gdm-disable-wayland"
+
# disable Wayland if modesetting is disabled
-IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-runtime-config set daemon WaylandEnable false"
+IMPORT{cmdline}="nomodeset", RUN+="@libexecdir@/gdm-disable-wayland"
--
2.27.0

View File

@ -1,44 +0,0 @@
From 13a617e15cca421962be888b5607a9900bbfef51 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 11 Feb 2019 18:14:07 -0500
Subject: [PATCH] data: disable wayland on server chips and dual gpu setups
We're still having a variety of issues on server chips and
dual gpu/hybrid graphics setups.
This commit forces Xorg for those cases.
---
data/61-gdm.rules.in | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index 26cf9cf51..e3631740d 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,5 +1,23 @@
# disable Wayland on Cirrus chipsets
ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="@libexecdir@/gdm-disable-wayland"
+# disable Wayland on Matrox chipsets
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland on aspeed chipsets
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland"
+ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland"
+
# disable Wayland when using the proprietary nvidia driver
DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland"
+
+# disable Wayland on hybrid graphics setups for now
+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", RUN+="@libexecdir@/gdm-disable-wayland"
+
--
2.21.0

View File

@ -1,44 +0,0 @@
From 7d9b41f1d82589999f8c89ed3bcc4eec6cee4978 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 6 Dec 2019 13:59:43 -0500
Subject: [PATCH] data: enable wayland on cirrus
cirrus in the 5.2 kernel was substantially rewritten and is more wayland
ready.
This commit reenables wayland on cirrus.
---
data/61-gdm.rules.in | 3 ---
1 file changed, 3 deletions(-)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index e3631740d..fc2e3315c 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,23 +1,20 @@
-# disable Wayland on Cirrus chipsets
-ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", RUN+="@libexecdir@/gdm-disable-wayland"
-
# disable Wayland on Matrox chipsets
ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland"
# disable Wayland on aspeed chipsets
ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland"
# disable Wayland when using the proprietary nvidia driver
DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland"
# disable Wayland on hybrid graphics setups for now
SUBSYSTEM=="drm", KERNEL=="card[1-9]*", RUN+="@libexecdir@/gdm-disable-wayland"
--
2.21.0

View File

@ -1,55 +0,0 @@
From ab9510df0b5f7bc29662804991729c6d6ee38b70 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 12 Dec 2019 16:56:16 -0500
Subject: [PATCH] data: only disable wayland on passthrough virt setups
at the moment we disable wayland on all hybrid graphics setups,
but most hybrid graphics setups work fine.
The case we really care about is passthrough virt. in that case,
wayland is a bad idea because:
1) kernel crashes
2) mutter provides no way to disable one of the cards, and will
always use one as a secondary gpu
This commit forces xorg in passthrough setups so the user can use
an xorg.conf to turn one of the cards off.
---
data/61-gdm.rules.in | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/data/61-gdm.rules.in b/data/61-gdm.rules.in
index fc2e3315c..f971224cf 100644
--- a/data/61-gdm.rules.in
+++ b/data/61-gdm.rules.in
@@ -1,20 +1,25 @@
# disable Wayland on Matrox chipsets
ATTR{vendor}=="0x102b", ATTR{device}=="0x0522", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0524", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0530", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0532", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0533", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0534", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0536", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x102b", ATTR{device}=="0x0538", RUN+="@libexecdir@/gdm-disable-wayland"
# disable Wayland on aspeed chipsets
ATTR{vendor}=="0x1a03", ATTR{device}=="0x2010", RUN+="@libexecdir@/gdm-disable-wayland"
ATTR{vendor}=="0x1a03", ATTR{device}=="0x2000", RUN+="@libexecdir@/gdm-disable-wayland"
# disable Wayland when using the proprietary nvidia driver
DRIVER=="nvidia", RUN+="@libexecdir@/gdm-disable-wayland"
-# disable Wayland on hybrid graphics setups for now
-SUBSYSTEM=="drm", KERNEL=="card[1-9]*", RUN+="@libexecdir@/gdm-disable-wayland"
+# disable Wayland on passthrough graphics setups for now (assumes passthrough if
+# there is more than one card, and one of the cards is virt: cirrus, bochs, qxl)
+ATTR{vendor}=="0x1013", ATTR{device}=="0x00b8", ATTR{subsystem_vendor}=="0x1af4", ATTR{subsystem_device}=="0x1100", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+ATTR{vendor}=="0x1b36", ATTR{device}=="0x0100", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+ATTR{vendor}=="0x1234", ATTR{device}=="0x1111", ENV{GDM_HAS_VIRTUAL_GPU}="1"
+
+SUBSYSTEM=="drm", KERNEL=="card[1-9]*", ENV{GDM_HAS_VIRTUAL_GPU}=="1", RUN+="@libexecdir@/gdm-disable-wayland"
--
2.21.0

View File

@ -0,0 +1,55 @@
From 7f910ee7554703a2e775e73ace10ced5d7a0fe66 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 17e8a8de8..195bd0fdc 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.28.0

View File

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

View File

@ -1,7 +1,7 @@
From f6a8a36717afc7ce00bdb2305a6219c28abc36fb Mon Sep 17 00:00:00 2001
From cbfb3ef99ecc9cbb4e6850e5dd0cc9fb65dd398a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 1 Sep 2020 13:49:27 -0400
Subject: [PATCH 51/51] display: Handle failure before display registration
Subject: [PATCH 1/3] display: Handle failure before display registration
Normally, e.g., gdm-wayland-session would register its display
before starting the session. This display registration is how
@ -17,14 +17,10 @@ display isn't yet fully managed.
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index ae20491cd..b8ccbbd72 100644
index 7c954ad24..3a260923a 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -575,80 +575,79 @@ gdm_display_disconnect (GdmDisplay *self)
return;
}
setup = xcb_get_setup (self->priv->xcb_connection);
@@ -648,62 +648,60 @@ gdm_display_disconnect (GdmDisplay *self)
/* resource_id_mask is the bits given to each client for
* addressing resources */
@ -38,40 +34,43 @@ index ae20491cd..b8ccbbd72 100644
client += client_increment) {
if (client != setup->resource_id_base)
xcb_kill_client (self->priv->xcb_connection, client);
xcb_kill_client (priv->xcb_connection, client);
}
xcb_flush (self->priv->xcb_connection);
xcb_flush (priv->xcb_connection);
g_clear_pointer (&self->priv->xcb_connection, xcb_disconnect);
g_clear_pointer (&priv->xcb_connection, xcb_disconnect);
}
gboolean
gdm_display_unmanage (GdmDisplay *self)
{
GdmDisplayPrivate *priv;
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
priv = gdm_display_get_instance_private (self);
- g_debug ("GdmDisplay: unmanage display");
-
gdm_display_disconnect (self);
if (self->priv->user_access_file != NULL) {
gdm_display_access_file_close (self->priv->user_access_file);
g_object_unref (self->priv->user_access_file);
self->priv->user_access_file = NULL;
if (priv->user_access_file != NULL) {
gdm_display_access_file_close (priv->user_access_file);
g_object_unref (priv->user_access_file);
priv->user_access_file = NULL;
}
if (self->priv->access_file != NULL) {
gdm_display_access_file_close (self->priv->access_file);
g_object_unref (self->priv->access_file);
self->priv->access_file = NULL;
if (priv->access_file != NULL) {
gdm_display_access_file_close (priv->access_file);
g_object_unref (priv->access_file);
priv->access_file = NULL;
}
if (!self->priv->session_registered) {
if (!priv->session_registered) {
g_warning ("GdmDisplay: Session never registered, failing");
_gdm_display_set_status (self, GDM_DISPLAY_FAILED);
} else {
+ g_debug ("GdmDisplay: Unmanage display");
_gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
}
@ -83,31 +82,13 @@ index ae20491cd..b8ccbbd72 100644
char **id,
GError **error)
{
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
if (id != NULL) {
*id = g_strdup (self->priv->id);
}
return TRUE;
}
gboolean
gdm_display_get_x11_display_name (GdmDisplay *self,
char **x11_display,
GError **error)
GdmDisplayPrivate *priv;
@@ -1446,63 +1444,63 @@ gdm_display_get_object_skeleton (GdmDisplay *self)
{
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
GdmDisplayPrivate *priv;
if (x11_display != NULL) {
*x11_display = g_strdup (self->priv->x11_display_name);
}
@@ -1309,63 +1308,62 @@ gdm_display_finalize (GObject *object)
GDBusObjectSkeleton *
gdm_display_get_object_skeleton (GdmDisplay *self)
{
return self->priv->object_skeleton;
priv = gdm_display_get_instance_private (self);
return priv->object_skeleton;
}
static void
@ -136,6 +117,7 @@ index ae20491cd..b8ccbbd72 100644
- if (gdm_display_get_status (self) == GDM_DISPLAY_MANAGED) {
- gdm_display_unmanage (self);
- }
+
+ g_debug ("GdmDisplay: initiating display self-destruct");
+ gdm_display_unmanage (self);
@ -169,5 +151,5 @@ index ae20491cd..b8ccbbd72 100644
{
g_debug ("GdmDisplay: Greeter died: %d", signal);
--
2.27.0
2.31.1

View File

@ -1,206 +0,0 @@
From fb55ec1c2e2957eb4c11a220874e5089fd357286 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 16 May 2018 14:06:29 -0400
Subject: [PATCH] display-access-file: drop unused function
gdm_display_access_file_remove_display is unused.
This commit drops it.
https://bugzilla.gnome.org/show_bug.cgi?id=796176
---
daemon/gdm-display-access-file.c | 79 --------------------------------
daemon/gdm-display-access-file.h | 3 --
2 files changed, 82 deletions(-)
diff --git a/daemon/gdm-display-access-file.c b/daemon/gdm-display-access-file.c
index 9bf818d2a..c1f0f17a8 100644
--- a/daemon/gdm-display-access-file.c
+++ b/daemon/gdm-display-access-file.c
@@ -536,139 +536,60 @@ gdm_display_access_file_add_display_with_cookie (GdmDisplayAccessFile *file,
|| fflush (file->priv->fp) == EOF) {
g_set_error (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
"%s", g_strerror (errno));
display_added = FALSE;
} else {
display_added = TRUE;
}
/* If we wrote a FamilyLocal entry, we still want a FamilyWild
* entry, because it's more resiliant against hostname changes
*
*/
if (auth_entry.family == FamilyLocal) {
auth_entry.family = FamilyWild;
if (XauWriteAuth (file->priv->fp, &auth_entry)
&& fflush (file->priv->fp) != EOF) {
display_added = TRUE;
}
}
g_free (auth_entry.address);
g_free (auth_entry.number);
g_free (auth_entry.name);
return display_added;
}
-gboolean
-gdm_display_access_file_remove_display (GdmDisplayAccessFile *file,
- GdmDisplay *display,
- GError **error)
-{
- Xauth *auth_entry;
- unsigned short family;
- unsigned short address_length;
- char *address;
- unsigned short number_length;
- char *number;
- unsigned short name_length;
- char *name;
-
- gboolean result = FALSE;
-
- g_return_val_if_fail (file != NULL, FALSE);
- g_return_val_if_fail (file->priv->path != NULL, FALSE);
-
- _get_auth_info_for_display (file, display,
- &family,
- &address_length,
- &address,
- &number_length,
- &number,
- &name_length,
- &name);
-
- auth_entry = XauGetAuthByAddr (family,
- address_length,
- address,
- number_length,
- number,
- name_length,
- name);
- g_free (address);
- g_free (number);
- g_free (name);
-
- if (auth_entry != NULL) {
- XauDisposeAuth (auth_entry);
- result = TRUE;
- }
-
- /* If FamilyLocal, we also added a FamilyWild entry,
- * so we need to clean that up too
- */
- if (family == FamilyLocal) {
- auth_entry = XauGetAuthByAddr (FamilyWild,
- address_length,
- address,
- number_length,
- number,
- name_length,
- name);
-
- if (auth_entry != NULL) {
- XauDisposeAuth (auth_entry);
- result = TRUE;
- }
- }
-
-
- if (result == FALSE) {
- g_set_error (error,
- GDM_DISPLAY_ACCESS_FILE_ERROR,
- GDM_DISPLAY_ACCESS_FILE_ERROR_FINDING_AUTH_ENTRY,
- "could not find authorization entry");
- } else if (fflush (file->priv->fp) == EOF) {
- g_set_error (error,
- G_FILE_ERROR,
- g_file_error_from_errno (errno),
- "%s", g_strerror (errno));
- result = FALSE;
- }
-
- return result;
-}
-
void
gdm_display_access_file_close (GdmDisplayAccessFile *file)
{
char *auth_dir;
g_return_if_fail (file != NULL);
g_return_if_fail (file->priv->fp != NULL);
g_return_if_fail (file->priv->path != NULL);
errno = 0;
if (g_unlink (file->priv->path) != 0) {
g_warning ("GdmDisplayAccessFile: Unable to remove X11 authority database '%s': %s",
file->priv->path,
g_strerror (errno));
}
/* still try to remove dir even if file remove failed,
may have already been removed by someone else */
/* we own the parent directory too */
auth_dir = g_path_get_dirname (file->priv->path);
if (auth_dir != NULL) {
errno = 0;
if (g_rmdir (auth_dir) != 0) {
g_warning ("GdmDisplayAccessFile: Unable to remove X11 authority directory '%s': %s",
auth_dir,
g_strerror (errno));
}
g_free (auth_dir);
}
diff --git a/daemon/gdm-display-access-file.h b/daemon/gdm-display-access-file.h
index cc7de9e35..eff8dd011 100644
--- a/daemon/gdm-display-access-file.h
+++ b/daemon/gdm-display-access-file.h
@@ -50,39 +50,36 @@ struct _GdmDisplayAccessFile
GdmDisplayAccessFilePrivate *priv;
};
struct _GdmDisplayAccessFileClass
{
GObjectClass parent_class;
};
enum _GdmDisplayAccessFileError
{
GDM_DISPLAY_ACCESS_FILE_ERROR_GENERAL = 0,
GDM_DISPLAY_ACCESS_FILE_ERROR_FINDING_AUTH_ENTRY
};
GQuark gdm_display_access_file_error_quark (void);
GType gdm_display_access_file_get_type (void);
GdmDisplayAccessFile *gdm_display_access_file_new (const char *username);
gboolean gdm_display_access_file_open (GdmDisplayAccessFile *file,
GError **error);
gboolean gdm_display_access_file_add_display (GdmDisplayAccessFile *file,
GdmDisplay *display,
char **cookie,
gsize *cookie_size,
GError **error);
gboolean gdm_display_access_file_add_display_with_cookie (GdmDisplayAccessFile *file,
GdmDisplay *display,
const char *cookie,
gsize cookie_size,
GError **error);
-gboolean gdm_display_access_file_remove_display (GdmDisplayAccessFile *file,
- GdmDisplay *display,
- GError **error);
void gdm_display_access_file_close (GdmDisplayAccessFile *file);
char *gdm_display_access_file_get_path (GdmDisplayAccessFile *file);
G_END_DECLS
#endif /* __GDM_DISPLAY_ACCESS_FILE_H__ */
--
2.17.1

View File

@ -1,269 +0,0 @@
From 781e865705b0c134271c9ec21655cd5d8ce37fec Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sat, 14 Dec 2019 13:50:53 -0500
Subject: [PATCH] display: ask accountservice if there are users rather than
enumerate users
At the moment we ask accountsservice to give us the list of users just
to find out if there is a list of users.
That's rather inefficient and might be wrong for directory server users
that have never logged in before.
This commit changes gdm to ask accountsservice the question we really
want to know the answer to; whether or not there are users.
---
daemon/gdm-display.c | 55 ++++++++++++++++++--------------------------
1 file changed, 22 insertions(+), 33 deletions(-)
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 878be88da..875534272 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -57,62 +57,60 @@
struct GdmDisplayPrivate
{
char *id;
char *seat_id;
char *session_id;
char *session_class;
char *session_type;
char *remote_hostname;
int x11_display_number;
char *x11_display_name;
int status;
time_t creation_time;
GTimer *server_timer;
char *x11_cookie;
gsize x11_cookie_size;
GdmDisplayAccessFile *access_file;
guint finish_idle_id;
xcb_connection_t *xcb_connection;
int xcb_screen_number;
GDBusConnection *connection;
GdmDisplayAccessFile *user_access_file;
GdmDBusDisplay *display_skeleton;
GDBusObjectSkeleton *object_skeleton;
- GDBusProxy *accountsservice_proxy;
-
/* this spawns and controls the greeter session */
GdmLaunchEnvironment *launch_environment;
guint is_local : 1;
guint is_initial : 1;
guint allow_timed_login : 1;
guint have_existing_user_accounts : 1;
guint doing_initial_setup : 1;
};
enum {
PROP_0,
PROP_ID,
PROP_STATUS,
PROP_SEAT_ID,
PROP_SESSION_ID,
PROP_SESSION_CLASS,
PROP_SESSION_TYPE,
PROP_REMOTE_HOSTNAME,
PROP_X11_DISPLAY_NUMBER,
PROP_X11_DISPLAY_NAME,
PROP_X11_COOKIE,
PROP_X11_AUTHORITY_FILE,
PROP_IS_CONNECTED,
PROP_IS_LOCAL,
PROP_LAUNCH_ENVIRONMENT,
PROP_IS_INITIAL,
PROP_ALLOW_TIMED_LOGIN,
PROP_HAVE_EXISTING_USER_ACCOUNTS,
PROP_DOING_INITIAL_SETUP,
@@ -512,96 +510,88 @@ queue_finish (GdmDisplay *self)
if (self->priv->finish_idle_id == 0) {
self->priv->finish_idle_id = g_idle_add ((GSourceFunc)finish_idle, self);
}
}
static void
_gdm_display_set_status (GdmDisplay *self,
int status)
{
if (status != self->priv->status) {
self->priv->status = status;
g_object_notify (G_OBJECT (self), "status");
}
}
static gboolean
gdm_display_real_prepare (GdmDisplay *self)
{
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
g_debug ("GdmDisplay: prepare display");
_gdm_display_set_status (self, GDM_DISPLAY_PREPARED);
return TRUE;
}
static void
look_for_existing_users_sync (GdmDisplay *self)
{
- GError *error = NULL;
- GVariant *call_result;
- GVariant *user_list;
-
- self->priv->accountsservice_proxy = g_dbus_proxy_new_sync (self->priv->connection,
- 0, NULL,
- "org.freedesktop.Accounts",
- "/org/freedesktop/Accounts",
- "org.freedesktop.Accounts",
- NULL,
- &error);
-
- if (!self->priv->accountsservice_proxy) {
- g_warning ("Failed to contact accountsservice: %s", error->message);
- goto out;
- }
-
- call_result = g_dbus_proxy_call_sync (self->priv->accountsservice_proxy,
- "ListCachedUsers",
- NULL,
- 0,
+ g_autoptr (GVariant) result = NULL;
+ g_autoptr (GVariant) result_child = NULL;
+ g_autoptr (GError) error = NULL;
+ gboolean has_no_users = FALSE;
+
+ result = g_dbus_connection_call_sync (self->priv->connection,
+ "org.freedesktop.Accounts",
+ "/org/freedesktop/Accounts",
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)", "org.freedesktop.Accounts", "HasNoUsers"),
+ G_VARIANT_TYPE ("(v)"),
+ G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
- if (!call_result) {
- g_warning ("Failed to list cached users: %s", error->message);
- goto out;
+ if (result == NULL) {
+ g_warning ("Failed to contact accountsservice: %s", error->message);
+ return;
}
- g_variant_get (call_result, "(@ao)", &user_list);
- self->priv->have_existing_user_accounts = g_variant_n_children (user_list) > 0;
- g_variant_unref (user_list);
- g_variant_unref (call_result);
-out:
- g_clear_error (&error);
+ g_variant_get (result, "(v)", &result_child);
+ has_no_users = g_variant_get_boolean (result_child);
+ self->priv->have_existing_user_accounts = !has_no_users;
+
+ g_debug ("GdmDisplay: machine does %shave existing user accounts",
+ has_no_users? "not " : "");
}
gboolean
gdm_display_prepare (GdmDisplay *self)
{
gboolean ret;
g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
g_debug ("GdmDisplay: Preparing display: %s", self->priv->id);
/* FIXME: we should probably do this in a more global place,
* asynchronously
*/
look_for_existing_users_sync (self);
self->priv->doing_initial_setup = wants_initial_setup (self);
g_object_ref (self);
ret = GDM_DISPLAY_GET_CLASS (self)->prepare (self);
g_object_unref (self);
return ret;
}
gboolean
gdm_display_manage (GdmDisplay *self)
{
gboolean res;
@@ -1332,61 +1322,60 @@ gdm_display_init (GdmDisplay *self)
self->priv = GDM_DISPLAY_GET_PRIVATE (self);
self->priv->creation_time = time (NULL);
self->priv->server_timer = g_timer_new ();
}
static void
gdm_display_finalize (GObject *object)
{
GdmDisplay *self;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_DISPLAY (object));
self = GDM_DISPLAY (object);
g_return_if_fail (self->priv != NULL);
g_debug ("GdmDisplay: Finalizing display: %s", self->priv->id);
g_free (self->priv->id);
g_free (self->priv->seat_id);
g_free (self->priv->session_class);
g_free (self->priv->remote_hostname);
g_free (self->priv->x11_display_name);
g_free (self->priv->x11_cookie);
g_clear_object (&self->priv->display_skeleton);
g_clear_object (&self->priv->object_skeleton);
g_clear_object (&self->priv->connection);
- g_clear_object (&self->priv->accountsservice_proxy);
if (self->priv->access_file != NULL) {
g_object_unref (self->priv->access_file);
}
if (self->priv->user_access_file != NULL) {
g_object_unref (self->priv->user_access_file);
}
if (self->priv->server_timer != NULL) {
g_timer_destroy (self->priv->server_timer);
}
G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
}
GDBusObjectSkeleton *
gdm_display_get_object_skeleton (GdmDisplay *self)
{
return self->priv->object_skeleton;
}
static void
on_launch_environment_session_opened (GdmLaunchEnvironment *launch_environment,
GdmDisplay *self)
{
char *session_id;
g_debug ("GdmDisplay: Greeter session opened");
session_id = gdm_launch_environment_get_session_id (launch_environment);
--
2.21.0

View File

@ -1,433 +0,0 @@
From a9422c7b5f4200ad36300bb06134d545bb9d48d2 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Tue, 17 Jul 2018 20:20:55 +0000
Subject: [PATCH 01/51] display-factory: avoid removing a display from store
while iterating it
---
daemon/gdm-display-factory.c | 41 ++++++++++++++++++++++++++++++
daemon/gdm-display-factory.h | 1 +
daemon/gdm-local-display-factory.c | 7 ++---
daemon/gdm-xdmcp-display-factory.c | 7 ++---
4 files changed, 46 insertions(+), 10 deletions(-)
diff --git a/daemon/gdm-display-factory.c b/daemon/gdm-display-factory.c
index d86a4c8ad..c520e1088 100644
--- a/daemon/gdm-display-factory.c
+++ b/daemon/gdm-display-factory.c
@@ -8,84 +8,120 @@
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include "gdm-display-factory.h"
#include "gdm-display-store.h"
#define GDM_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY_FACTORY, GdmDisplayFactoryPrivate))
struct GdmDisplayFactoryPrivate
{
GdmDisplayStore *display_store;
+ guint purge_displays_id;
};
enum {
PROP_0,
PROP_DISPLAY_STORE,
};
static void gdm_display_factory_class_init (GdmDisplayFactoryClass *klass);
static void gdm_display_factory_init (GdmDisplayFactory *factory);
static void gdm_display_factory_finalize (GObject *object);
G_DEFINE_ABSTRACT_TYPE (GdmDisplayFactory, gdm_display_factory, G_TYPE_OBJECT)
GQuark
gdm_display_factory_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_display_factory_error");
}
return ret;
}
+static gboolean
+purge_display (char *id,
+ GdmDisplay *display,
+ gpointer user_data)
+{
+ int status;
+
+ status = gdm_display_get_status (display);
+
+ switch (status) {
+ case GDM_DISPLAY_FINISHED:
+ case GDM_DISPLAY_FAILED:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+static void
+purge_displays (GdmDisplayFactory *factory)
+{
+ factory->priv->purge_displays_id = 0;
+ gdm_display_store_foreach_remove (factory->priv->display_store,
+ (GdmDisplayStoreFunc)purge_display,
+ NULL);
+}
+
+void
+gdm_display_factory_queue_purge_displays (GdmDisplayFactory *factory)
+{
+ if (factory->priv->purge_displays_id == 0) {
+ factory->priv->purge_displays_id = g_idle_add ((GSourceFunc) purge_displays, factory);
+ }
+}
+
GdmDisplayStore *
gdm_display_factory_get_display_store (GdmDisplayFactory *factory)
{
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), NULL);
return factory->priv->display_store;
}
gboolean
gdm_display_factory_start (GdmDisplayFactory *factory)
{
gboolean ret;
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
g_object_ref (factory);
ret = GDM_DISPLAY_FACTORY_GET_CLASS (factory)->start (factory);
g_object_unref (factory);
return ret;
}
gboolean
gdm_display_factory_stop (GdmDisplayFactory *factory)
{
gboolean ret;
g_return_val_if_fail (GDM_IS_DISPLAY_FACTORY (factory), FALSE);
g_object_ref (factory);
@@ -160,32 +196,37 @@ gdm_display_factory_class_init (GdmDisplayFactoryClass *klass)
g_object_class_install_property (object_class,
PROP_DISPLAY_STORE,
g_param_spec_object ("display-store",
"display store",
"display store",
GDM_TYPE_DISPLAY_STORE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (GdmDisplayFactoryPrivate));
}
static void
gdm_display_factory_init (GdmDisplayFactory *factory)
{
factory->priv = GDM_DISPLAY_FACTORY_GET_PRIVATE (factory);
}
static void
gdm_display_factory_finalize (GObject *object)
{
GdmDisplayFactory *factory;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_DISPLAY_FACTORY (object));
factory = GDM_DISPLAY_FACTORY (object);
g_return_if_fail (factory->priv != NULL);
+ if (factory->priv->purge_displays_id != 0) {
+ g_source_remove (factory->priv->purge_displays_id);
+ factory->priv->purge_displays_id = 0;
+ }
+
G_OBJECT_CLASS (gdm_display_factory_parent_class)->finalize (object);
}
diff --git a/daemon/gdm-display-factory.h b/daemon/gdm-display-factory.h
index 6b30f83dc..1cffa1bd5 100644
--- a/daemon/gdm-display-factory.h
+++ b/daemon/gdm-display-factory.h
@@ -37,34 +37,35 @@ G_BEGIN_DECLS
typedef struct GdmDisplayFactoryPrivate GdmDisplayFactoryPrivate;
typedef struct
{
GObject parent;
GdmDisplayFactoryPrivate *priv;
} GdmDisplayFactory;
typedef struct
{
GObjectClass parent_class;
gboolean (*start) (GdmDisplayFactory *factory);
gboolean (*stop) (GdmDisplayFactory *factory);
} GdmDisplayFactoryClass;
typedef enum
{
GDM_DISPLAY_FACTORY_ERROR_GENERAL
} GdmDisplayFactoryError;
#define GDM_DISPLAY_FACTORY_ERROR gdm_display_factory_error_quark ()
GQuark gdm_display_factory_error_quark (void);
GType gdm_display_factory_get_type (void);
gboolean gdm_display_factory_start (GdmDisplayFactory *manager);
gboolean gdm_display_factory_stop (GdmDisplayFactory *manager);
GdmDisplayStore * gdm_display_factory_get_display_store (GdmDisplayFactory *manager);
+void gdm_display_factory_queue_purge_displays (GdmDisplayFactory *manager);
G_END_DECLS
#endif /* __GDM_DISPLAY_FACTORY_H */
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index ab7e12e91..1a9196ee1 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -222,107 +222,104 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
"seat-id", "seat0",
"allow-timed-login", FALSE,
NULL);
store_display (factory, display);
if (! gdm_display_manage (display)) {
display = NULL;
goto out;
}
if (! gdm_display_get_id (display, id, NULL)) {
display = NULL;
goto out;
}
ret = TRUE;
out:
/* ref either held by store or not at all */
g_object_unref (display);
return ret;
}
static void
on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory)
{
int status;
- GdmDisplayStore *store;
int num;
char *seat_id = NULL;
char *session_type = NULL;
gboolean is_initial = TRUE;
gboolean is_local = TRUE;
num = -1;
gdm_display_get_x11_display_number (display, &num, NULL);
- store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
-
g_object_get (display,
"seat-id", &seat_id,
"is-initial", &is_initial,
"is-local", &is_local,
"session-type", &session_type,
NULL);
status = gdm_display_get_status (display);
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
switch (status) {
case GDM_DISPLAY_FINISHED:
/* remove the display number from factory->priv->used_display_numbers
so that it may be reused */
if (num != -1) {
g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
}
- gdm_display_store_remove (store, display);
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
/* if this is a local display, do a full resync. Only
* seats without displays will get created anyway. This
* ensures we get a new login screen when the user logs out,
* if there isn't one.
*/
if (is_local) {
/* reset num failures */
factory->priv->num_failures = 0;
gdm_local_display_factory_sync_seats (factory);
}
break;
case GDM_DISPLAY_FAILED:
/* leave the display number in factory->priv->used_display_numbers
so that it doesn't get reused */
- gdm_display_store_remove (store, display);
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
/* Create a new equivalent display if it was static */
if (is_local) {
factory->priv->num_failures++;
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
/* oh shit */
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
} else {
#ifdef ENABLE_WAYLAND_SUPPORT
if (g_strcmp0 (session_type, "wayland") == 0) {
g_free (session_type);
session_type = NULL;
/* workaround logind race for now
* bug 1643874
*/
g_usleep (2 * G_USEC_PER_SEC);
}
#endif
create_display (factory, seat_id, session_type, is_initial);
}
}
break;
case GDM_DISPLAY_UNMANAGED:
break;
case GDM_DISPLAY_PREPARED:
break;
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
index 46a0d9ffa..5b5786c6f 100644
--- a/daemon/gdm-xdmcp-display-factory.c
+++ b/daemon/gdm-xdmcp-display-factory.c
@@ -2039,93 +2039,90 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display,
char *ip;
ic->chosen_address = gdm_address_new_from_sockaddr (ai->ai_addr, ai->ai_addrlen);
ip = NULL;
gdm_address_get_numeric_info (ic->chosen_address, &ip, NULL);
g_debug ("GdmXdmcpDisplayFactory: hostname resolves to %s",
ip ? ip : "(null)");
g_free (ip);
}
freeaddrinfo (ai_list);
}
static void
on_client_disconnected (GdmDisplay *display)
{
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
return;
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
}
static void
on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmXdmcpDisplayFactory *factory)
{
int status;
- GdmDisplayStore *store;
GdmLaunchEnvironment *launch_environment;
GdmSession *session;
GdmAddress *address;
gint32 session_number;
int display_number;
- store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
-
launch_environment = NULL;
g_object_get (display, "launch-environment", &launch_environment, NULL);
session = NULL;
if (launch_environment != NULL) {
session = gdm_launch_environment_get_session (launch_environment);
}
status = gdm_display_get_status (display);
g_debug ("GdmXdmcpDisplayFactory: xdmcp display status changed: %d", status);
switch (status) {
case GDM_DISPLAY_FINISHED:
g_object_get (display,
"remote-address", &address,
"x11-display-number", &display_number,
"session-number", &session_number,
NULL);
gdm_xdmcp_send_alive (factory, address, display_number, session_number);
- gdm_display_store_remove (store, display);
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
break;
case GDM_DISPLAY_FAILED:
- gdm_display_store_remove (store, display);
+ gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
break;
case GDM_DISPLAY_UNMANAGED:
if (session != NULL) {
g_signal_handlers_disconnect_by_func (G_OBJECT (session),
G_CALLBACK (on_client_disconnected),
display);
}
break;
case GDM_DISPLAY_PREPARED:
break;
case GDM_DISPLAY_MANAGED:
if (session != NULL) {
g_signal_connect_object (G_OBJECT (session),
"client-disconnected",
G_CALLBACK (on_client_disconnected),
display, G_CONNECT_SWAPPED);
g_signal_connect_object (G_OBJECT (session),
"disconnected",
G_CALLBACK (on_client_disconnected),
display, G_CONNECT_SWAPPED);
}
break;
default:
g_assert_not_reached ();
break;
}
}
static GdmDisplay *
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
--
2.27.0

View File

@ -0,0 +1,325 @@
From d8fd8d4d6ff6a119f6bd27eb07316384c4776d12 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 11dcda2c..a0884893 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) {
@@ -478,60 +480,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 */
@@ -1250,99 +1256,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 b3d0a2b5..4b62b8b1 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -2774,60 +2774,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.31.1

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
From f9662449f0f7dbb452ba11fe85a3c81b386f6dab Mon Sep 17 00:00:00 2001
From 903dd62114d24a90fe55a7cf42ea07233fe71879 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 29 Oct 2018 06:57:59 -0400
Subject: [PATCH] local-display-factory: pause for a few seconds before falling
back to X
Subject: [PATCH] local-display-factory: pause for a few seconds before
falling back to X
logind currently gets confused if a session is started immediately as
one is shutting down.
@ -12,79 +12,81 @@ back to X.
http://bugzilla.redhat.com/1643874
---
daemon/gdm-local-display-factory.c | 5 +++++
1 file changed, 5 insertions(+)
daemon/gdm-local-display-factory.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 403921d32..ab7e12e91 100644
index eba38671..948c5d98 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -283,60 +283,65 @@ on_display_status_changed (GdmDisplay *display,
/* if this is a local display, do a full resync. Only
* seats without displays will get created anyway. This
* ensures we get a new login screen when the user logs out,
* if there isn't one.
*/
if (is_local) {
/* reset num failures */
factory->priv->num_failures = 0;
@@ -653,60 +653,67 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
preferred_display_server = get_preferred_display_server (factory);
gdm_local_display_factory_sync_seats (factory);
}
break;
case GDM_DISPLAY_FAILED:
/* leave the display number in factory->priv->used_display_numbers
so that it doesn't get reused */
gdm_display_store_remove (store, display);
/* Create a new equivalent display if it was static */
if (is_local) {
factory->priv->num_failures++;
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
/* oh shit */
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
} else {
#ifdef ENABLE_WAYLAND_SUPPORT
if (g_strcmp0 (session_type, "wayland") == 0) {
g_free (session_type);
session_type = NULL;
+
+ /* workaround logind race for now
+ * bug 1643874
+ */
+ g_usleep (2 * G_USEC_PER_SEC);
}
#endif
create_display (factory, seat_id, session_type, is_initial);
}
}
break;
case GDM_DISPLAY_UNMANAGED:
break;
case GDM_DISPLAY_PREPARED:
break;
case GDM_DISPLAY_MANAGED:
break;
default:
g_assert_not_reached ();
break;
if (g_strcmp0 (preferred_display_server, "none") == 0) {
g_debug ("GdmLocalDisplayFactory: Preferred display server is none, so not creating display");
return;
}
g_free (seat_id);
g_free (session_type);
}
ret = sd_seat_can_graphical (seat_id);
static gboolean
lookup_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
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 (falling_back) {
+ /* workaround logind race for now
+ * bug 1643874
+ */
+ g_usleep (2 * G_USEC_PER_SEC);
+ }
} 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.19.1
2.27.0

View File

@ -1,353 +0,0 @@
From de229615d80fd7c8a38ab5d5d7b30aa98f43721d Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 14 Sep 2020 16:20:09 -0400
Subject: [PATCH 1/3] manager: Don't leak session objects
The first is from create_user_session_for display. Most callers don't
check the return value, so it should just be void.
The user data associated with the session also isn't unlinked from the
display when the display is finishing up, preventing the display and
session object from getting freed.
This commit makes both changes.
---
daemon/gdm-manager.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index bff602a07..738671679 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -94,63 +94,63 @@ struct GdmManagerPrivate
#ifdef WITH_PLYMOUTH
guint plymouth_is_running : 1;
#endif
guint did_automatic_login : 1;
};
enum {
PROP_0,
PROP_XDMCP_ENABLED,
PROP_SHOW_LOCAL_GREETER
};
enum {
DISPLAY_ADDED,
DISPLAY_REMOVED,
LAST_SIGNAL
};
typedef enum {
SESSION_RECORD_LOGIN,
SESSION_RECORD_LOGOUT,
SESSION_RECORD_FAILED,
} SessionRecord;
static guint signals [LAST_SIGNAL] = { 0, };
static void gdm_manager_class_init (GdmManagerClass *klass);
static void gdm_manager_init (GdmManager *manager);
static void gdm_manager_dispose (GObject *object);
-static GdmSession *create_user_session_for_display (GdmManager *manager,
- GdmDisplay *display,
- uid_t allowed_user);
+static void create_user_session_for_display (GdmManager *manager,
+ GdmDisplay *display,
+ uid_t allowed_user);
static void start_user_session (GdmManager *manager,
StartUserSessionOperation *operation);
static void clean_user_session (GdmSession *session);
static gpointer manager_object = NULL;
static void manager_interface_init (GdmDBusManagerIface *interface);
G_DEFINE_TYPE_WITH_CODE (GdmManager,
gdm_manager,
GDM_DBUS_TYPE_MANAGER_SKELETON,
G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_MANAGER,
manager_interface_init));
#ifdef WITH_PLYMOUTH
static gboolean
plymouth_is_running (void)
{
int status;
gboolean res;
GError *error;
error = NULL;
res = g_spawn_command_line_sync ("/bin/plymouth --ping",
NULL, NULL, &status, &error);
if (! res) {
g_debug ("Could not ping plymouth: %s", error->message);
g_error_free (error);
return FALSE;
}
@@ -1343,61 +1343,62 @@ get_automatic_login_details (GdmManager *manager,
return enabled;
}
static const char *
get_username_for_greeter_display (GdmManager *manager,
GdmDisplay *display)
{
gboolean doing_initial_setup = FALSE;
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
NULL);
if (doing_initial_setup) {
return INITIAL_SETUP_USERNAME;
} else {
return GDM_USERNAME;
}
}
static void
set_up_automatic_login_session (GdmManager *manager,
GdmDisplay *display)
{
GdmSession *session;
char *display_session_type = NULL;
/* 0 is root user; since the daemon talks to the session object
* directly, itself, for automatic login
*/
- session = create_user_session_for_display (manager, display, 0);
+ create_user_session_for_display (manager, display, 0);
+ session = get_user_session_for_display (display);
g_object_get (G_OBJECT (display),
"session-type", &display_session_type,
NULL);
g_object_set (G_OBJECT (session),
"display-is-initial", FALSE,
NULL);
g_debug ("GdmManager: Starting automatic login conversation");
gdm_session_start_conversation (session, "gdm-autologin");
}
static void
set_up_chooser_session (GdmManager *manager,
GdmDisplay *display)
{
const char *allowed_user;
struct passwd *passwd_entry;
allowed_user = get_username_for_greeter_display (manager, display);
if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
g_warning ("GdmManager: couldn't look up username %s",
allowed_user);
gdm_display_unmanage (display);
gdm_display_finish (display);
return;
}
@@ -1549,60 +1550,62 @@ on_display_status_changed (GdmDisplay *display,
"session-type", &session_type,
NULL);
status = gdm_display_get_status (display);
switch (status) {
case GDM_DISPLAY_PREPARED:
case GDM_DISPLAY_MANAGED:
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
char *session_class;
g_object_get (display,
"session-class", &session_class,
NULL);
if (g_strcmp0 (session_class, "greeter") == 0)
set_up_session (manager, display);
g_free (session_class);
}
break;
case GDM_DISPLAY_FAILED:
case GDM_DISPLAY_UNMANAGED:
case GDM_DISPLAY_FINISHED:
#ifdef WITH_PLYMOUTH
if (quit_plymouth) {
plymouth_quit_without_transition ();
manager->priv->plymouth_is_running = FALSE;
}
#endif
+ g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
+
if (display == manager->priv->automatic_login_display) {
g_clear_weak_pointer (&manager->priv->automatic_login_display);
manager->priv->did_automatic_login = TRUE;
#ifdef ENABLE_WAYLAND_SUPPORT
if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) {
/* we're going to fall back to X11, so try to autologin again
*/
manager->priv->did_automatic_login = FALSE;
}
#endif
}
break;
default:
break;
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmManager *manager)
{
char *id;
gdm_display_get_id (display, &id, NULL);
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
g_free (id);
@@ -2292,61 +2295,61 @@ on_session_reauthentication_started (GdmSession *session,
int pid_of_caller,
const char *address,
GdmManager *manager)
{
GDBusMethodInvocation *invocation;
gpointer source_tag;
g_debug ("GdmManager: reauthentication started");
source_tag = GINT_TO_POINTER (pid_of_caller);
invocation = g_hash_table_lookup (manager->priv->open_reauthentication_requests,
source_tag);
if (invocation != NULL) {
g_hash_table_steal (manager->priv->open_reauthentication_requests,
source_tag);
gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
invocation,
address);
}
}
static void
clean_user_session (GdmSession *session)
{
g_object_set_data (G_OBJECT (session), "gdm-display", NULL);
g_object_unref (session);
}
-static GdmSession *
+static void
create_user_session_for_display (GdmManager *manager,
GdmDisplay *display,
uid_t allowed_user)
{
GdmSession *session;
gboolean display_is_local = FALSE;
char *display_name = NULL;
char *display_device = NULL;
char *remote_hostname = NULL;
char *display_auth_file = NULL;
char *display_seat_id = NULL;
char *display_id = NULL;
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
char *display_session_type = NULL;
gboolean greeter_is_wayland;
#endif
g_object_get (G_OBJECT (display),
"id", &display_id,
"x11-display-name", &display_name,
"is-local", &display_is_local,
"remote-hostname", &remote_hostname,
"x11-authority-file", &display_auth_file,
"seat-id", &display_seat_id,
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
"session-type", &display_session_type,
#endif
NULL);
display_device = get_display_device (manager, display);
@@ -2402,70 +2405,68 @@ create_user_session_for_display (GdmManager *manager,
"conversation-stopped",
G_CALLBACK (on_session_conversation_stopped),
manager);
g_signal_connect (session,
"authentication-failed",
G_CALLBACK (on_session_authentication_failed),
manager);
g_signal_connect (session,
"session-opened",
G_CALLBACK (on_user_session_opened),
manager);
g_signal_connect (session,
"session-started",
G_CALLBACK (on_user_session_started),
manager);
g_signal_connect (session,
"session-start-failed",
G_CALLBACK (on_session_start_failed),
manager);
g_signal_connect (session,
"session-exited",
G_CALLBACK (on_user_session_exited),
manager);
g_signal_connect (session,
"session-died",
G_CALLBACK (on_user_session_died),
manager);
g_object_set_data (G_OBJECT (session), "gdm-display", display);
g_object_set_data_full (G_OBJECT (display),
"gdm-user-session",
- g_object_ref (session),
+ session,
(GDestroyNotify)
clean_user_session);
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
greeter_is_wayland = g_strcmp0 (display_session_type, "wayland") == 0;
g_object_set (G_OBJECT (session), "ignore-wayland", !greeter_is_wayland, NULL);
#endif
-
- return session;
}
static void
on_display_added (GdmDisplayStore *display_store,
const char *id,
GdmManager *manager)
{
GdmDisplay *display;
display = gdm_display_store_lookup (display_store, id);
if (display != NULL) {
g_dbus_object_manager_server_export (manager->priv->object_manager,
gdm_display_get_object_skeleton (display));
g_signal_connect (display, "notify::status",
G_CALLBACK (on_display_status_changed),
manager);
g_signal_emit (manager, signals[DISPLAY_ADDED], 0, id);
}
}
GQuark
gdm_manager_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_manager_error");
}
--
2.26.2

View File

@ -1,28 +1,28 @@
From bb58b5762272840a414f2bfe3ab59d733099a06c Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
From d80807171a457ff87bdc9bd861939161749a37a8 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/2] manager: allow multiple xdmcp logins for the same user
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.in | 5 +++
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 f0059b5cf..33676a851 100644
index 87685d3cd..4b3a1ffeb 100644
--- a/common/gdm-settings-keys.h
+++ b/common/gdm-settings-keys.h
@@ -28,37 +28,38 @@ G_BEGIN_DECLS
#define GDM_KEY_USER "daemon/User"
#define GDM_KEY_GROUP "daemon/Group"
@@ -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"
@ -53,11 +53,10 @@ index f0059b5cf..33676a851 100644
#endif /* _GDM_SETTINGS_KEYS_H */
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 056560b20..de7357ad5 100644
index e433acf3b..ce8565bf9 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -594,93 +594,106 @@ get_display_and_details_for_bus_sender (GdmManager *self,
if (out_tty != NULL) {
@@ -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) {
@ -71,10 +70,11 @@ index 056560b20..de7357ad5 100644
lookup_by_session_id,
(gpointer) session_id);
out:
if (out_display != NULL) {
*out_display = display;
}
out:
g_free (session_id);
}
@ -112,7 +112,7 @@ index 056560b20..de7357ad5 100644
- if (existing_session != NULL) {
- ssid_to_activate = gdm_session_get_session_id (existing_session);
- if (seat_id != NULL) {
- res = activate_session_id (manager, seat_id, ssid_to_activate);
- res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate);
- if (! res) {
- g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate);
- goto out;
@ -138,7 +138,7 @@ index 056560b20..de7357ad5 100644
}
+ if (seat_id != NULL) {
+ res = activate_session_id (manager, seat_id, ssid_to_activate);
+ res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate);
+ if (! res) {
+ g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate);
+ goto out;
@ -181,7 +181,7 @@ index 056560b20..de7357ad5 100644
{
const char *username;
char *display_name, *hostname, *display_device;
@@ -1088,92 +1101,114 @@ open_temporary_reauthentication_channel (GdmManager *self,
@@ -1089,92 +1102,114 @@ open_temporary_reauthentication_channel (GdmManager *self,
g_signal_connect (session,
"client-disconnected",
G_CALLBACK (on_reauthentication_client_disconnected),
@ -263,7 +263,7 @@ index 056560b20..de7357ad5 100644
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_ACCESS_DENIED,
+ "Login screen creates new sessions for remote connections");
+ return TRUE;
+ return TRUE;
+ }
+
if (is_login_screen) {
@ -296,11 +296,11 @@ index 056560b20..de7357ad5 100644
pid,
uid,
is_remote);
diff --git a/data/gdm.schemas.in.in b/data/gdm.schemas.in.in
index 8ad203101..003f92c63 100644
--- a/data/gdm.schemas.in.in
+++ b/data/gdm.schemas.in.in
@@ -102,32 +102,37 @@
diff --git a/data/gdm.schemas.in b/data/gdm.schemas.in
index a1035f95e..929d13d90 100644
--- a/data/gdm.schemas.in
+++ b/data/gdm.schemas.in
@@ -112,33 +112,38 @@
<schema>
<key>xdmcp/DisplaysPerHost</key>
<signature>i</signature>
@ -338,6 +338,7 @@ index 8ad203101..003f92c63 100644
+ </schema>
</schemalist>
</gdmschemafile>
--
2.21.1
--
2.30.1

View File

@ -1,87 +0,0 @@
From ecd37ba6d56a49dd896613f68d1e1754633b9f0c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 6 Feb 2019 16:14:52 -0500
Subject: [PATCH 1/4] manager: don't kill timed login session immediately after
it starts
At the moment GDM is misidentifying timed login sessions as if
they are automatic login sessions. That leads to their displays
getting killed sometimes shortly after log in.
This commit corrects the check, so that timed login sessions aren't
treated as autologin sessions.
---
daemon/gdm-manager.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 1943d89e4..72d44b006 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1838,61 +1838,62 @@ on_start_user_session (StartUserSessionOperation *operation)
NULL);
} else {
uid_t allowed_uid;
g_object_ref (display);
if (doing_initial_setup) {
g_debug ("GdmManager: closing down initial setup display");
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
/* We can't start the user session until the finished display
* starts to respawn (since starting an X server and bringing
* one down at the same time is a no go)
*/
g_assert (self->priv->initial_login_operation == NULL);
self->priv->initial_login_operation = operation;
starting_user_session_right_away = FALSE;
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
- if (g_strcmp0 (operation->service_name, "gdm-autologin") == 0) {
+ if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
+ !gdm_session_client_is_connected (operation->session)) {
/* remove the unused prepared greeter display since we're not going
* to have a greeter */
gdm_display_store_remove (self->priv->display_store, display);
g_object_unref (display);
}
/* Give the user session a new display object for bookkeeping purposes */
create_display_for_user_session (operation->manager,
operation->session,
session_id);
}
if (starting_user_session_right_away) {
start_user_session (operation->manager, operation);
}
out:
return G_SOURCE_REMOVE;
}
static void
queue_start_user_session (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
StartUserSessionOperation *operation;
operation = g_slice_new0 (StartUserSessionOperation);
operation->manager = manager;
operation->session = g_object_ref (session);
--
2.26.0

View File

@ -1,683 +0,0 @@
From 3864af1ea06d2125c1b1f5afa6fc12caa833980a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 10 Dec 2020 15:14:20 -0500
Subject: [PATCH] session-worker: Don't switch back VTs until session is fully
exited
There's a race condition on shutdown where the session worker is
switching VTs back to the initial VT at the same time as the session
exit is being processed.
This means that manager may try to start a login screen (because of
the VT switch) when autologin is enabled when there shouldn't be a
login screen.
This commit makes sure both the PostSession script, and session-exited
signal emission are complete before initiating the VT switch back
to the initial VT.
https://gitlab.gnome.org/GNOME/gdm/-/issues/660
---
daemon/Makefile.am | 12 +++++
daemon/gdm-session-worker.c | 93 +++++++++++++++++++++++++++------
daemon/org.freedesktop.DBus.xml | 12 +++++
3 files changed, 101 insertions(+), 16 deletions(-)
create mode 100644 daemon/org.freedesktop.DBus.xml
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 86a8ee32f..b323f6455 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -7,83 +7,92 @@ AM_CPPFLAGS = \
-I$(top_srcdir)/pam-extensions \
-I$(top_builddir)/common \
-DBINDIR=\"$(bindir)\" \
-DDATADIR=\"$(datadir)\" \
-DDMCONFDIR=\"$(dmconfdir)\" \
-DGDMCONFDIR=\"$(gdmconfdir)\" \
-DLIBDIR=\"$(libdir)\" \
-DLIBEXECDIR=\"$(libexecdir)\" \
-DLOCALSTATEDIR=\"$(localstatedir)\" \
-DLOGDIR=\"$(logdir)\" \
-DSBINDIR=\"$(sbindir)\" \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \
-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
-DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \
-DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
-DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
$(DISABLE_DEPRECATED_CFLAGS) \
$(DAEMON_CFLAGS) \
$(XLIB_CFLAGS) \
$(WARN_CFLAGS) \
$(DEBUG_CFLAGS) \
$(SYSTEMD_CFLAGS) \
$(JOURNALD_CFLAGS) \
$(LIBSELINUX_CFLAGS) \
-DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \
$(NULL)
BUILT_SOURCES = \
+ gdm-dbus-glue.h \
gdm-display-glue.h \
gdm-manager-glue.h \
gdm-local-display-glue.h \
gdm-local-display-factory-glue.h \
gdm-session-glue.h \
gdm-session-worker-glue.h \
gdm-session-enum-types.h \
gdm-session-worker-enum-types.h \
com.redhat.AccountsServiceUser.System.h \
$(NULL)
gdm-session-enum-types.h: gdm-session-enum-types.h.in gdm-session.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
gdm-session-enum-types.c: gdm-session-enum-types.c.in gdm-session.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
gdm-session-worker-enum-types.h: gdm-session-worker-enum-types.h.in gdm-session-worker.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
gdm-session-worker-enum-types.c: gdm-session-worker-enum-types.c.in gdm-session-worker.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
+gdm-dbus-glue.c gdm-dbus-glue.h: org.freedesktop.DBus.xml Makefile.am
+ $(AM_V_GEN)gdbus-codegen \
+ --c-namespace=GdmDBus \
+ --interface-prefix=org.freedesktop.DBus \
+ --generate-c-code=gdm-dbus-glue \
+ --c-generate-autocleanup=all \
+ $(srcdir)/org.freedesktop.DBus.xml
+
gdm-display-glue.c gdm-display-glue.h: gdm-display.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-display-glue \
$(srcdir)/gdm-display.xml
gdm-local-display-glue.c gdm-local-display-glue.h: gdm-local-display.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-local-display-glue \
$(srcdir)/gdm-local-display.xml
gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-display-factory.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-local-display-factory-glue \
$(srcdir)/gdm-local-display-factory.xml
gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-manager-glue \
$(srcdir)/gdm-manager.xml
gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
@@ -130,60 +139,62 @@ libexec_PROGRAMS = \
gdm-wayland-session \
gdm-x-session \
$(NULL)
gdm_session_worker_SOURCES = \
session-worker-main.c \
com.redhat.AccountsServiceUser.System.h \
com.redhat.AccountsServiceUser.System.c \
gdm-session.c \
gdm-session.h \
gdm-session-settings.h \
gdm-session-settings.c \
gdm-session-auditor.h \
gdm-session-auditor.c \
gdm-session-record.c \
gdm-session-record.h \
gdm-session-worker.h \
gdm-session-worker.c \
gdm-session-worker-job.c \
gdm-session-worker-common.c \
gdm-session-worker-common.h \
gdm-dbus-util.c \
gdm-dbus-util.h \
$(NULL)
if SUPPORTS_PAM_EXTENSIONS
gdm_session_worker_SOURCES += $(top_srcdir)/pam-extensions/gdm-pam-extensions.h
endif
nodist_gdm_session_worker_SOURCES = \
+ gdm-dbus-glue.h \
+ gdm-dbus-glue.c \
gdm-session-glue.h \
gdm-session-glue.c \
gdm-session-worker-glue.c \
gdm-session-worker-glue.h \
gdm-session-enum-types.c \
gdm-session-worker-enum-types.c \
gdm-session-enum-types.h \
$(NULL)
gdm_wayland_session_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(GTK_LIBS) \
$(COMMON_LIBS) \
$(SYSTEMD_LIBS) \
$(NULL)
gdm_wayland_session_SOURCES = \
gdm-manager-glue.h \
gdm-manager-glue.c \
gdm-wayland-session.c \
$(NULL)
gdm_x_session_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(GTK_LIBS) \
$(COMMON_LIBS) \
$(SYSTEMD_LIBS) \
$(XLIB_LIBS) \
$(NULL)
@@ -271,50 +282,51 @@ nodist_gdm_SOURCES = \
XDMCP_SOURCES = \
gdm-xdmcp-display-factory.c \
gdm-xdmcp-display-factory.h \
gdm-xdmcp-display.c \
gdm-xdmcp-display.h \
gdm-xdmcp-chooser-display.c \
gdm-xdmcp-chooser-display.h \
$(NULL)
if XDMCP_SUPPORT
gdm_SOURCES += $(XDMCP_SOURCES)
endif
EXTRA_gdm_SOURCES = \
$(XDMCP_SOURCES) \
$(NULL)
gdm_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(XLIB_LIBS) \
$(DAEMON_LIBS) \
$(XDMCP_LIBS) \
$(LIBWRAP_LIBS) \
$(SYSTEMD_LIBS) \
$(JOURNALD_LIBS) \
$(EXTRA_DAEMON_LIBS) \
$(NULL)
CLEANFILES = \
+ gdm-dbus-glue.c \
gdm-display-glue.c \
gdm-local-display-factory-glue.c \
gdm-manager-glue.c \
gdm-session-glue.c \
gdm-session-worker-glue.c \
gdm-session-enum-types.c \
gdm-local-display-glue.c \
$(BUILT_SOURCES) \
$(NULL)
EXTRA_DIST = \
gdm-manager.xml \
gdm-session-worker.xml \
gdm-session.xml \
gdm-display.xml \
gdm-local-display.xml \
gdm-local-display-factory.xml \
gdm-session-enum-types.c.in \
gdm-session-enum-types.h.in \
$(NULL)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 42c415837..c1b2c1765 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -39,60 +39,61 @@
#ifdef HAVE_LOGINCAP
#include <login_cap.h>
#endif
#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <X11/Xauth.h>
#include <systemd/sd-daemon.h>
#ifdef ENABLE_SYSTEMD_JOURNAL
#include <systemd/sd-journal.h>
#endif
#ifdef HAVE_SELINUX
#include <selinux/selinux.h>
#endif /* HAVE_SELINUX */
#include "gdm-common.h"
#include "gdm-log.h"
#ifdef SUPPORTS_PAM_EXTENSIONS
#include "gdm-pam-extensions.h"
#endif
+#include "gdm-dbus-glue.h"
#include "gdm-session-worker.h"
#include "gdm-session-glue.h"
#include "gdm-session.h"
#if defined (HAVE_ADT)
#include "gdm-session-solaris-auditor.h"
#elif defined (HAVE_LIBAUDIT)
#include "gdm-session-linux-auditor.h"
#else
#include "gdm-session-auditor.h"
#endif
#include "gdm-session-settings.h"
#define GDM_SESSION_WORKER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerPrivate))
#define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session"
#define GDM_SESSION_DBUS_NAME "org.gnome.DisplayManager.Session"
#define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
#define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker"
#ifndef GDM_PASSWD_AUXILLARY_BUFFER_SIZE
#define GDM_PASSWD_AUXILLARY_BUFFER_SIZE 1024
#endif
#ifndef GDM_SESSION_DEFAULT_PATH
#define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin"
#endif
@@ -1028,72 +1029,60 @@ gdm_session_worker_set_state (GdmSessionWorker *worker,
static void
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
int status)
{
g_debug ("GdmSessionWorker: uninitializing PAM");
if (worker->priv->pam_handle == NULL)
return;
gdm_session_worker_get_username (worker, NULL);
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
pam_close_session (worker->priv->pam_handle, 0);
gdm_session_auditor_report_logout (worker->priv->auditor);
} else {
gdm_session_auditor_report_login_failure (worker->priv->auditor,
status,
pam_strerror (worker->priv->pam_handle, status));
}
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) {
pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED);
}
pam_end (worker->priv->pam_handle, status);
worker->priv->pam_handle = NULL;
gdm_session_worker_stop_auditor (worker);
- /* If user-display-server is not enabled the login_vt is always
- * identical to the session_vt. So in that case we never need to
- * do a VT switch. */
-#ifdef ENABLE_USER_DISPLAY_SERVER
- if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
- /* Switch to the login VT if we are not the login screen. */
- if (worker->priv->session_vt != GDM_INITIAL_VT) {
- jump_to_vt (worker, GDM_INITIAL_VT);
- }
- }
-#endif
-
worker->priv->session_vt = 0;
g_debug ("GdmSessionWorker: state NONE");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE);
}
static char *
_get_tty_for_pam (const char *x11_display_name,
const char *display_device)
{
#ifdef __sun
return g_strdup (display_device);
#else
return g_strdup (x11_display_name);
#endif
}
#ifdef PAM_XAUTHDATA
static struct pam_xauth_data *
_get_xauth_for_pam (const char *x11_authority_file)
{
FILE *fh;
Xauth *auth = NULL;
struct pam_xauth_data *retval = NULL;
gsize len = sizeof (*retval) + 1;
fh = fopen (x11_authority_file, "r");
if (fh) {
auth = XauReadAuth (fh);
fclose (fh);
@@ -1752,86 +1741,155 @@ gdm_session_worker_accredit_user (GdmSessionWorker *worker,
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCREDITED);
} else {
gdm_session_worker_uninitialize_pam (worker, error_code);
}
return ret;
}
static const char * const *
gdm_session_worker_get_environment (GdmSessionWorker *worker)
{
return (const char * const *) pam_getenvlist (worker->priv->pam_handle);
}
static gboolean
run_script (GdmSessionWorker *worker,
const char *dir)
{
/* scripts are for non-program sessions only */
if (worker->priv->is_program_session) {
return TRUE;
}
return gdm_run_script (dir,
worker->priv->username,
worker->priv->x11_display_name,
worker->priv->display_is_local? NULL : worker->priv->hostname,
worker->priv->x11_authority_file);
}
+static void
+wait_until_dbus_signal_emission_to_manager_finishes (GdmSessionWorker *worker)
+{
+ g_autoptr (GdmDBusPeer) peer_proxy = NULL;
+ g_autoptr (GError) error = NULL;
+ gboolean pinged;
+
+ peer_proxy = gdm_dbus_peer_proxy_new_sync (worker->priv->connection,
+ G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+ NULL,
+ "/org/freedesktop/DBus",
+ NULL,
+ &error);
+
+ if (peer_proxy == NULL) {
+ g_debug ("GdmSessionWorker: could not create peer proxy to daemon: %s",
+ error->message);
+ return;
+ }
+
+ pinged = gdm_dbus_peer_call_ping_sync (peer_proxy, NULL, &error);
+
+ if (!pinged) {
+ g_debug ("GdmSessionWorker: could not ping daemon: %s",
+ error->message);
+ return;
+ }
+}
+
+static void
+jump_back_to_initial_vt (GdmSessionWorker *worker)
+{
+ if (worker->priv->session_vt == 0)
+ return;
+
+ if (worker->priv->session_vt == GDM_INITIAL_VT)
+ return;
+
+ if (g_strcmp0 (worker->priv->display_seat_id, "seat0") != 0)
+ return;
+
+#ifdef ENABLE_USER_DISPLAY_SERVER
+ jump_to_vt (worker, GDM_INITIAL_VT);
+ worker->priv->session_vt = 0;
+#endif
+}
+
static void
session_worker_child_watch (GPid pid,
int status,
GdmSessionWorker *worker)
{
g_debug ("GdmSessionWorker: child (pid:%d) done (%s:%d)",
(int) pid,
WIFEXITED (status) ? "status"
: WIFSIGNALED (status) ? "signal"
: "unknown",
WIFEXITED (status) ? WEXITSTATUS (status)
: WIFSIGNALED (status) ? WTERMSIG (status)
: -1);
-
gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
+ worker->priv->child_pid = -1;
+ worker->priv->child_watch_id = 0;
+ run_script (worker, GDMCONFDIR "/PostSession");
+
gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker),
worker->priv->service,
status);
killpg (pid, SIGHUP);
- worker->priv->child_pid = -1;
- worker->priv->child_watch_id = 0;
- run_script (worker, GDMCONFDIR "/PostSession");
+ /* FIXME: It's important to give the manager an opportunity to process the
+ * session-exited emission above before switching VTs.
+ *
+ * This is because switching VTs makes the manager try to put a login screen
+ * up on VT 1, but it may actually want to try to auto login again in response
+ * to session-exited.
+ *
+ * This function just does a manager roundtrip over the bus to make sure the
+ * signal has been dispatched before jumping.
+ *
+ * Ultimately, we may want to improve the manager<->worker interface.
+ *
+ * See:
+ *
+ * https://gitlab.gnome.org/GNOME/gdm/-/merge_requests/123
+ *
+ * for some ideas and more discussion.
+ *
+ */
+ wait_until_dbus_signal_emission_to_manager_finishes (worker);
+
+ jump_back_to_initial_vt (worker);
}
static void
gdm_session_worker_watch_child (GdmSessionWorker *worker)
{
g_debug ("GdmSession worker: watching pid %d", worker->priv->child_pid);
worker->priv->child_watch_id = g_child_watch_add (worker->priv->child_pid,
(GChildWatchFunc)session_worker_child_watch,
worker);
}
static gboolean
_is_loggable_file (const char* filename)
{
struct stat file_info;
if (g_lstat (filename, &file_info) < 0) {
return FALSE;
}
return S_ISREG (file_info.st_mode) && g_access (filename, R_OK | W_OK) == 0;
}
static void
rotate_logs (const char *path,
guint n_copies)
{
int i;
@@ -2401,60 +2459,61 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
flags = 0;
if (worker->priv->is_program_session) {
flags |= PAM_SILENT;
}
error_code = pam_open_session (worker->priv->pam_handle, flags);
if (error_code != PAM_SUCCESS) {
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
"%s", pam_strerror (worker->priv->pam_handle, error_code));
goto out;
}
g_debug ("GdmSessionWorker: state SESSION_OPENED");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_OPENED);
session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
if (session_id != NULL) {
g_free (worker->priv->session_id);
worker->priv->session_id = session_id;
}
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
+ worker->priv->session_vt = 0;
return FALSE;
}
gdm_session_worker_get_username (worker, NULL);
gdm_session_auditor_report_login (worker->priv->auditor);
return TRUE;
}
static void
gdm_session_worker_set_server_address (GdmSessionWorker *worker,
const char *address)
{
g_free (worker->priv->server_address);
worker->priv->server_address = g_strdup (address);
}
static void
gdm_session_worker_set_is_reauth_session (GdmSessionWorker *worker,
gboolean is_reauth_session)
{
worker->priv->is_reauth_session = is_reauth_session;
}
static void
gdm_session_worker_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
@@ -3565,60 +3624,62 @@ gdm_session_worker_unwatch_child (GdmSessionWorker *worker)
return;
g_source_remove (worker->priv->child_watch_id);
worker->priv->child_watch_id = 0;
}
static void
gdm_session_worker_finalize (GObject *object)
{
GdmSessionWorker *worker;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_SESSION_WORKER (object));
worker = GDM_SESSION_WORKER (object);
g_return_if_fail (worker->priv != NULL);
gdm_session_worker_unwatch_child (worker);
if (worker->priv->child_pid > 0) {
gdm_signal_pid (worker->priv->child_pid, SIGTERM);
gdm_wait_on_pid (worker->priv->child_pid);
}
if (worker->priv->pam_handle != NULL) {
gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
}
+ jump_back_to_initial_vt (worker);
+
g_clear_object (&worker->priv->user_settings);
g_free (worker->priv->service);
g_free (worker->priv->x11_display_name);
g_free (worker->priv->x11_authority_file);
g_free (worker->priv->display_device);
g_free (worker->priv->display_seat_id);
g_free (worker->priv->hostname);
g_free (worker->priv->username);
g_free (worker->priv->server_address);
g_strfreev (worker->priv->arguments);
g_strfreev (worker->priv->extensions);
g_hash_table_unref (worker->priv->reauthentication_requests);
G_OBJECT_CLASS (gdm_session_worker_parent_class)->finalize (object);
}
GdmSessionWorker *
gdm_session_worker_new (const char *address,
gboolean is_reauth_session)
{
GObject *object;
object = g_object_new (GDM_TYPE_SESSION_WORKER,
"server-address", address,
"is-reauth-session", is_reauth_session,
NULL);
return GDM_SESSION_WORKER (object);
}
diff --git a/daemon/org.freedesktop.DBus.xml b/daemon/org.freedesktop.DBus.xml
new file mode 100644
index 000000000..5e0814bde
--- /dev/null
+++ b/daemon/org.freedesktop.DBus.xml
@@ -0,0 +1,12 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.freedesktop.DBus.Peer">
+ <method name="GetMachineId">
+ <arg direction="out" type="s"/>
+ </method>
+ <method name="Ping">
+ </method>
+ </interface>
+</node>
+
--
2.28.0

View File

@ -1,470 +0,0 @@
From 521ff70fe447558461dd38cdec62a7c0a5a74f7a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 24 Jun 2019 14:48:23 -0400
Subject: [PATCH 1/3] session-worker: expose worker state enum to type system
We're going to need to access the worker state as a property on
the worker object.
This commit hooks it up to glib-mkenums so the requisite goo can
get generated
---
daemon/Makefile.am | 8 +++++
daemon/gdm-session-worker-enum-types.c.in | 42 +++++++++++++++++++++++
daemon/gdm-session-worker-enum-types.h.in | 24 +++++++++++++
daemon/gdm-session-worker.c | 16 +++------
daemon/gdm-session-worker.h | 12 +++++++
5 files changed, 90 insertions(+), 12 deletions(-)
create mode 100644 daemon/gdm-session-worker-enum-types.c.in
create mode 100644 daemon/gdm-session-worker-enum-types.h.in
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index b77c9276e..86a8ee32f 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -14,69 +14,76 @@ AM_CPPFLAGS = \
-DLIBEXECDIR=\"$(libexecdir)\" \
-DLOCALSTATEDIR=\"$(localstatedir)\" \
-DLOGDIR=\"$(logdir)\" \
-DSBINDIR=\"$(sbindir)\" \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \
-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
-DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \
-DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
-DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
$(DISABLE_DEPRECATED_CFLAGS) \
$(DAEMON_CFLAGS) \
$(XLIB_CFLAGS) \
$(WARN_CFLAGS) \
$(DEBUG_CFLAGS) \
$(SYSTEMD_CFLAGS) \
$(JOURNALD_CFLAGS) \
$(LIBSELINUX_CFLAGS) \
-DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \
$(NULL)
BUILT_SOURCES = \
gdm-display-glue.h \
gdm-manager-glue.h \
gdm-local-display-glue.h \
gdm-local-display-factory-glue.h \
gdm-session-glue.h \
gdm-session-worker-glue.h \
gdm-session-enum-types.h \
+ gdm-session-worker-enum-types.h \
com.redhat.AccountsServiceUser.System.h \
$(NULL)
gdm-session-enum-types.h: gdm-session-enum-types.h.in gdm-session.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
gdm-session-enum-types.c: gdm-session-enum-types.c.in gdm-session.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
+gdm-session-worker-enum-types.h: gdm-session-worker-enum-types.h.in gdm-session-worker.h
+ $(AM_V_GEN) glib-mkenums --template $^ > $@
+
+gdm-session-worker-enum-types.c: gdm-session-worker-enum-types.c.in gdm-session-worker.h
+ $(AM_V_GEN) glib-mkenums --template $^ > $@
+
gdm-display-glue.c gdm-display-glue.h: gdm-display.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-display-glue \
$(srcdir)/gdm-display.xml
gdm-local-display-glue.c gdm-local-display-glue.h: gdm-local-display.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-local-display-glue \
$(srcdir)/gdm-local-display.xml
gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-display-factory.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-local-display-factory-glue \
$(srcdir)/gdm-local-display-factory.xml
gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-manager-glue \
$(srcdir)/gdm-manager.xml
gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
@@ -128,60 +135,61 @@ gdm_session_worker_SOURCES = \
session-worker-main.c \
com.redhat.AccountsServiceUser.System.h \
com.redhat.AccountsServiceUser.System.c \
gdm-session.c \
gdm-session.h \
gdm-session-settings.h \
gdm-session-settings.c \
gdm-session-auditor.h \
gdm-session-auditor.c \
gdm-session-record.c \
gdm-session-record.h \
gdm-session-worker.h \
gdm-session-worker.c \
gdm-session-worker-job.c \
gdm-session-worker-common.c \
gdm-session-worker-common.h \
gdm-dbus-util.c \
gdm-dbus-util.h \
$(NULL)
if SUPPORTS_PAM_EXTENSIONS
gdm_session_worker_SOURCES += $(top_srcdir)/pam-extensions/gdm-pam-extensions.h
endif
nodist_gdm_session_worker_SOURCES = \
gdm-session-glue.h \
gdm-session-glue.c \
gdm-session-worker-glue.c \
gdm-session-worker-glue.h \
gdm-session-enum-types.c \
+ gdm-session-worker-enum-types.c \
gdm-session-enum-types.h \
$(NULL)
gdm_wayland_session_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(GTK_LIBS) \
$(COMMON_LIBS) \
$(SYSTEMD_LIBS) \
$(NULL)
gdm_wayland_session_SOURCES = \
gdm-manager-glue.h \
gdm-manager-glue.c \
gdm-wayland-session.c \
$(NULL)
gdm_x_session_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(GTK_LIBS) \
$(COMMON_LIBS) \
$(SYSTEMD_LIBS) \
$(XLIB_LIBS) \
$(NULL)
gdm_x_session_SOURCES = \
gdm-manager-glue.h \
gdm-manager-glue.c \
gdm-x-session.c \
$(NULL)
diff --git a/daemon/gdm-session-worker-enum-types.c.in b/daemon/gdm-session-worker-enum-types.c.in
new file mode 100644
index 000000000..c02869076
--- /dev/null
+++ b/daemon/gdm-session-worker-enum-types.c.in
@@ -0,0 +1,42 @@
+/*** BEGIN file-header ***/
+
+#include <glib-object.h>
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+#include "@filename@"
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+
+GType
+@enum_name@_get_type (void)
+{
+ static GType etype = 0;
+
+ if (G_UNLIKELY(etype == 0)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL }
+ };
+
+ etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
+ }
+
+ return etype;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+ /**/
+/*** END file-tail ***/
diff --git a/daemon/gdm-session-worker-enum-types.h.in b/daemon/gdm-session-worker-enum-types.h.in
new file mode 100644
index 000000000..64f4b4bb6
--- /dev/null
+++ b/daemon/gdm-session-worker-enum-types.h.in
@@ -0,0 +1,24 @@
+/*** BEGIN file-header ***/
+#ifndef GDM_SESSION_WORKER_ENUM_TYPES_H
+#define GDM_SESSION_WORKER_ENUM_TYPES_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* GDM_SESSION_WORKER_ENUM_TYPES_H */
+/*** END file-tail ***/
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index ae86d28ac..f6935ab1d 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -83,83 +83,72 @@
#define GDM_SESSION_WORKER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerPrivate))
#define GDM_SESSION_DBUS_PATH "/org/gnome/DisplayManager/Session"
#define GDM_SESSION_DBUS_NAME "org.gnome.DisplayManager.Session"
#define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
#define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker"
#ifndef GDM_PASSWD_AUXILLARY_BUFFER_SIZE
#define GDM_PASSWD_AUXILLARY_BUFFER_SIZE 1024
#endif
#ifndef GDM_SESSION_DEFAULT_PATH
#define GDM_SESSION_DEFAULT_PATH "/usr/local/bin:/usr/bin:/bin"
#endif
#ifndef GDM_SESSION_ROOT_UID
#define GDM_SESSION_ROOT_UID 0
#endif
#ifndef GDM_SESSION_LOG_FILENAME
#define GDM_SESSION_LOG_FILENAME "session.log"
#endif
#define MAX_FILE_SIZE 65536
#define MAX_LOGS 5
#define RELEASE_DISPLAY_SIGNAL (SIGRTMAX)
#define ACQUIRE_DISPLAY_SIGNAL (SIGRTMAX - 1)
-enum {
- GDM_SESSION_WORKER_STATE_NONE = 0,
- GDM_SESSION_WORKER_STATE_SETUP_COMPLETE,
- GDM_SESSION_WORKER_STATE_AUTHENTICATED,
- GDM_SESSION_WORKER_STATE_AUTHORIZED,
- GDM_SESSION_WORKER_STATE_ACCREDITED,
- GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED,
- GDM_SESSION_WORKER_STATE_SESSION_OPENED,
- GDM_SESSION_WORKER_STATE_SESSION_STARTED
-};
-
typedef struct
{
GdmSessionWorker *worker;
GdmSession *session;
GPid pid_of_caller;
uid_t uid_of_caller;
} ReauthenticationRequest;
struct GdmSessionWorkerPrivate
{
- int state;
+ GdmSessionWorkerState state;
int exit_code;
pam_handle_t *pam_handle;
GPid child_pid;
guint child_watch_id;
/* from Setup */
char *service;
char *x11_display_name;
char *x11_authority_file;
char *display_device;
char *display_seat_id;
char *hostname;
char *username;
char *log_file;
char *session_id;
uid_t uid;
gid_t gid;
gboolean password_is_required;
char **extensions;
int cred_flags;
int login_vt;
int session_vt;
int session_tty_fd;
char **arguments;
guint32 cancelled : 1;
@@ -2455,60 +2444,63 @@ gdm_session_worker_set_property (GObject *object,
switch (prop_id) {
case PROP_SERVER_ADDRESS:
gdm_session_worker_set_server_address (self, g_value_get_string (value));
break;
case PROP_IS_REAUTH_SESSION:
gdm_session_worker_set_is_reauth_session (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_session_worker_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdmSessionWorker *self;
self = GDM_SESSION_WORKER (object);
switch (prop_id) {
case PROP_SERVER_ADDRESS:
g_value_set_string (value, self->priv->server_address);
break;
case PROP_IS_REAUTH_SESSION:
g_value_set_boolean (value, self->priv->is_reauth_session);
break;
+ case PROP_STATE:
+ g_value_set_int (value, self->priv->state);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gdm_session_worker_handle_set_environment_variable (GdmDBusWorker *object,
GDBusMethodInvocation *invocation,
const char *key,
const char *value)
{
GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
gdm_session_worker_set_environment_variable (worker, key, value);
gdm_dbus_worker_complete_set_environment_variable (object, invocation);
return TRUE;
}
static gboolean
gdm_session_worker_handle_set_session_name (GdmDBusWorker *object,
GDBusMethodInvocation *invocation,
const char *session_name)
{
GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
g_debug ("GdmSessionWorker: session name set to %s", session_name);
if (worker->priv->user_settings != NULL)
gdm_session_settings_set_session_name (worker->priv->user_settings,
session_name);
gdm_dbus_worker_complete_set_session_name (object, invocation);
return TRUE;
diff --git a/daemon/gdm-session-worker.h b/daemon/gdm-session-worker.h
index 5603e80e0..2814eab4d 100644
--- a/daemon/gdm-session-worker.h
+++ b/daemon/gdm-session-worker.h
@@ -1,56 +1,68 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2006 Ray Strode <rstrode@redhat.com>
*
* 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, 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_SESSION_WORKER_H
#define __GDM_SESSION_WORKER_H
#include <glib-object.h>
#include "gdm-session-worker-glue.h"
#include "gdm-session-worker-common.h"
+#include "gdm-session-worker-enum-types.h"
G_BEGIN_DECLS
#define GDM_TYPE_SESSION_WORKER (gdm_session_worker_get_type ())
#define GDM_SESSION_WORKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDM_TYPE_SESSION_WORKER, GdmSessionWorker))
#define GDM_SESSION_WORKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerClass))
#define GDM_IS_SESSION_WORKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDM_TYPE_SESSION_WORKER))
#define GDM_IS_SESSION_WORKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDM_TYPE_SESSION_WORKER))
#define GDM_SESSION_WORKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GDM_TYPE_SESSION_WORKER, GdmSessionWorkerClass))
+typedef enum {
+ GDM_SESSION_WORKER_STATE_NONE = 0,
+ GDM_SESSION_WORKER_STATE_SETUP_COMPLETE,
+ GDM_SESSION_WORKER_STATE_AUTHENTICATED,
+ GDM_SESSION_WORKER_STATE_AUTHORIZED,
+ GDM_SESSION_WORKER_STATE_ACCREDITED,
+ GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED,
+ GDM_SESSION_WORKER_STATE_SESSION_OPENED,
+ GDM_SESSION_WORKER_STATE_SESSION_STARTED
+} GdmSessionWorkerState;
+
typedef struct GdmSessionWorkerPrivate GdmSessionWorkerPrivate;
typedef struct
{
GdmDBusWorkerSkeleton parent;
GdmSessionWorkerPrivate *priv;
} GdmSessionWorker;
typedef struct
{
GdmDBusWorkerSkeletonClass parent_class;
} GdmSessionWorkerClass;
GType gdm_session_worker_get_type (void);
GdmSessionWorker * gdm_session_worker_new (const char *server_address,
gboolean is_for_reauth) G_GNUC_MALLOC;
G_END_DECLS
#endif /* GDM_SESSION_WORKER_H */
--
2.18.1

View File

@ -0,0 +1,362 @@
From 7b5ee288d992f85eaefbfbc4dac663a29fcae446 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 5 May 2021 11:06:58 -0400
Subject: [PATCH] 0001-utils-Drop-gdm-screenshot.patch
---
utils/gdm-screenshot.c | 296 -----------------------------------------
utils/meson.build | 15 ---
2 files changed, 311 deletions(-)
delete mode 100644 utils/gdm-screenshot.c
diff --git a/utils/gdm-screenshot.c b/utils/gdm-screenshot.c
deleted file mode 100644
index 5d20929a3..000000000
--- a/utils/gdm-screenshot.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
- *
- * 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 <unistd.h>
-#include <string.h>
-#include <locale.h>
-
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <canberra-gtk.h>
-
-#include <X11/Xatom.h>
-#include <gdk/gdkx.h>
-
-#define SELECTION_NAME "_GDM_SCREENSHOT"
-static GtkWidget *selection_window;
-
-static gboolean debug_in;
-
-/* Keep all config options for compatibility even if they are noops */
-GOptionEntry options [] = {
- { "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_in, N_("Debugging output"), NULL },
- { NULL }
-};
-
-/* To make sure there is only one screenshot taken at a time,
- * (Imagine key repeat for the print screen key) we hold a selection
- * until we are done taking the screenshot
- */
-/* * Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu> */
-static gboolean
-screenshot_grab_lock (void)
-{
- Atom selection_atom;
- GdkCursor *cursor;
- gboolean result = FALSE;
-
- selection_atom = gdk_x11_get_xatom_by_name (SELECTION_NAME);
- XGrabServer (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
- if (XGetSelectionOwner (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), selection_atom) != None) {
- goto out;
- }
-
- selection_window = gtk_invisible_new ();
- gtk_widget_show (selection_window);
-
- if (!gtk_selection_owner_set (selection_window,
- gdk_atom_intern (SELECTION_NAME, FALSE),
- GDK_CURRENT_TIME)) {
- gtk_widget_destroy (selection_window);
- selection_window = NULL;
- goto out;
- }
-
- cursor = gdk_cursor_new_for_display (gdk_display_get_default (), GDK_WATCH);
- gdk_pointer_grab (gtk_widget_get_window (selection_window), FALSE, 0, NULL,
- cursor, GDK_CURRENT_TIME);
- g_object_unref (cursor);
-
- result = TRUE;
-
- out:
- XUngrabServer (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
- gdk_flush ();
-
- return result;
-}
-
-/* * Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu> */
-static void
-screenshot_release_lock (void)
-{
- if (selection_window != NULL) {
- gtk_widget_destroy (selection_window);
- selection_window = NULL;
- }
- gdk_flush ();
-}
-
-/* * Copyright (C) 2001-2006 Jonathan Blandford <jrb@alum.mit.edu> */
-static GdkPixbuf *
-screenshot_get_pixbuf (Window w)
-{
- GdkWindow *window;
- GdkWindow *root;
- GdkPixbuf *screenshot;
- int x_real_orig;
- int y_real_orig;
- int x_orig;
- int y_orig;
- int real_width;
- int real_height;
- int width;
- int height;
-
- window = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), w);
- if (window == NULL) {
- return NULL;
- }
-
- root = gdk_x11_window_foreign_new_for_display (gdk_display_get_default (), GDK_ROOT_WINDOW ());
- gdk_window_get_geometry (window, NULL, NULL, &real_width, &real_height);
- gdk_window_get_origin (window, &x_real_orig, &y_real_orig);
-
- x_orig = x_real_orig;
- y_orig = y_real_orig;
- width = real_width;
- height = real_height;
-
- if (x_orig < 0) {
- width = width + x_orig;
- x_orig = 0;
- }
- if (y_orig < 0) {
- height = height + y_orig;
- y_orig = 0;
- }
-
- if (x_orig + width > gdk_screen_width ()) {
- width = gdk_screen_width () - x_orig;
- }
- if (y_orig + height > gdk_screen_height ()) {
- height = gdk_screen_height () - y_orig;
- }
-
- screenshot = gdk_pixbuf_get_from_window (root,
- x_orig,
- y_orig,
- width,
- height);
-
- return screenshot;
-}
-
-static char *
-screenshot_save (GdkPixbuf *pixbuf)
-{
- char *filename;
- gboolean res;
- GError *error;
-
- filename = g_build_filename (GDM_SCREENSHOT_DIR,
- "GDM-Screenshot.png",
- NULL);
-
- error = NULL;
- res = gdk_pixbuf_save (pixbuf,
- filename,
- "png",
- &error,
- "tEXt::CREATOR", "gdm-screenshot",
- NULL);
- if (! res) {
- g_warning ("Unable to save screenshot: %s", error->message);
- g_error_free (error);
- g_free (filename);
- filename = NULL;
- }
-
- return filename;
-}
-
-static void
-sound_effect_finished (ca_context *c,
- uint32_t id,
- int error_code,
- void *userdata)
-{
-}
-
-static void
-play_sound_effect (Window xid)
-{
- ca_context *c;
- ca_proplist *p;
- int res;
-
- c = ca_gtk_context_get ();
-
- p = NULL;
- res = ca_proplist_create (&p);
- if (res < 0) {
- goto done;
- }
-
- res = ca_proplist_sets (p, CA_PROP_EVENT_ID, "screen-capture");
- if (res < 0) {
- goto done;
- }
-
- res = ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Screenshot taken"));
- if (res < 0) {
- goto done;
- }
-
- res = ca_proplist_setf (p,
- CA_PROP_WINDOW_X11_XID,
- "%lu",
- (unsigned long) xid);
- if (res < 0) {
- goto done;
- }
-
- ca_context_play_full (c, 0, p, sound_effect_finished, NULL);
-
- done:
- if (p != NULL) {
- ca_proplist_destroy (p);
- }
-
-}
-
-static void
-prepare_screenshot (void)
-{
- Window win;
- GdkPixbuf *screenshot;
- char *filename;
-
- if (!screenshot_grab_lock ()) {
- exit (EXIT_SUCCESS);
- }
-
- win = GDK_ROOT_WINDOW ();
-
- screenshot = screenshot_get_pixbuf (win);
-
- screenshot_release_lock ();
-
- if (screenshot == NULL) {
- /* FIXME: dialog? */
- exit (EXIT_FAILURE);
- }
-
- play_sound_effect (win);
-
- filename = screenshot_save (screenshot);
- if (filename != NULL) {
- g_print ("Wrote %s\n", filename);
- /* FIXME: show a dialog or something */
- g_free (filename);
- }
-}
-
-int
-main (int argc, char *argv[])
-{
- GOptionContext *ctx;
- gboolean res;
- GError *error;
-
- bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
- bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
- textdomain (GETTEXT_PACKAGE);
- setlocale (LC_ALL, "");
-
- /* Option parsing */
- ctx = g_option_context_new (N_("Take a picture of the screen"));
- g_option_context_set_translation_domain (ctx, GETTEXT_PACKAGE);
- g_option_context_add_main_entries (ctx, options, NULL);
- g_option_context_add_group (ctx, gtk_get_option_group (TRUE));
- error = NULL;
- res = g_option_context_parse (ctx, &argc, &argv, &error);
- g_option_context_free (ctx);
-
- if (! res) {
- g_warning ("%s", error->message);
- g_error_free (error);
- exit (EXIT_FAILURE);
- }
-
- prepare_screenshot ();
-
- return 1;
-}
diff --git a/utils/meson.build b/utils/meson.build
index d59f167b0..1edd7bce4 100644
--- a/utils/meson.build
+++ b/utils/meson.build
@@ -1,41 +1,26 @@
# gdm-flexiserver
gdm_flexiserver_deps = [
glib_dep,
libgdmcommon_dep,
]
gdm_flexiserver = executable('gdmflexiserver',
'gdmflexiserver.c',
dependencies: gdm_flexiserver_deps,
include_directories: config_h_dir,
install: true,
)
-# gdm-screenshot
-gdm_screenshot_deps = [
- glib_dep,
- gtk_dep,
- x_deps,
- libcanberra_gtk_dep,
-]
-
-gdm_screenshot = executable('gdm-screenshot',
- 'gdm-screenshot.c',
- dependencies: gdm_screenshot_deps,
- include_directories: config_h_dir,
- install: true,
-)
-
# gdm-runtime-config
gdm_runtime_config_deps = [
glib_dep,
]
gdm_runtime_config = executable('gdm-runtime-config',
'gdm-runtime-config.c',
dependencies: gdm_runtime_config_deps,
include_directories: config_h_dir,
install: true,
install_dir: get_option('libexecdir'),
)
--
2.31.1

View File

@ -1,161 +0,0 @@
From 14656db42a6b4d4d48cf74127f3187dfe85607ec Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 21 May 2018 15:03:29 +0000
Subject: [PATCH] utils: add new gdm-disable-wayland binary
We currently disable wayland for cirrus by calling printf
from a udev rule. This works, but it's a little too open
coded to easily write SELinux policy for.
This commit introduces a new program, gdm-disable-wayland,
that does the same thing, but in a dedicated binary.
A future commit will change the udev rule to use the binary.
https://bugzilla.gnome.org/show_bug.cgi?id=796315
(cherry picked from commit 2dc57da31781dedfe374ce353b0f5fd6aa9da56f)
---
utils/Makefile.am | 14 ++++++++++
utils/gdm-disable-wayland.c | 53 +++++++++++++++++++++++++++++++++++++
2 files changed, 67 insertions(+)
create mode 100644 utils/gdm-disable-wayland.c
diff --git a/utils/Makefile.am b/utils/Makefile.am
index ae3cc01fb..babe890b9 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -1,56 +1,70 @@
NULL =
AM_CPPFLAGS = \
-I$(srcdir) \
-I$(builddir) \
-I$(top_srcdir) \
-I$(top_builddir) \
-I$(top_srcdir)/common \
-I$(top_builddir)/common \
-DDATADIR=\"$(datadir)\" \
-DGDMCONFDIR=\"$(gdmconfdir)\" \
-DLOCALSTATEDIR=\""$(localstatedir)"\" \
+ -DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \
+ -DGDM_RUNTIME_CONF=\"$(GDM_RUNTIME_CONF)\" \
-DGDM_SCREENSHOT_DIR=\""$(GDM_SCREENSHOT_DIR)"\"\
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
$(UTILS_CFLAGS) \
$(CANBERRA_GTK_CFLAGS) \
$(GTK_CFLAGS) \
$(XLIB_CFLAGS) \
$(SYSTEMD_CFLAGS) \
$(COMMON_CFLAGS) \
$(NULL)
edit = sed \
-e 's|@sbindir[@]|$(sbindir)|g' \
-e 's|@sysconfdir[@]|$(sysconfdir)|g' \
-e 's|@localstatedir[@]|$(localstatedir)|g' \
-e 's|@GDM_PID_FILE[@]|$(GDM_PID_FILE)|g'
bin_PROGRAMS = \
gdmflexiserver \
gdm-screenshot \
$(NULL)
+libexec_PROGRAMS = \
+ gdm-disable-wayland \
+ $(NULL)
+
gdmflexiserver_LDADD = \
$(top_builddir)/common/libgdmcommon.la \
$(GTK_LIBS) \
$(COMMON_LIBS) \
$(SYSTEMD_LIBS) \
$(NULL)
gdm_screenshot_SOURCES = \
gdm-screenshot.c \
$(NULL)
gdm_screenshot_LDADD = \
$(GTK_LIBS) \
$(CANBERRA_GTK_LIBS) \
$(XLIB_LIBS) \
$(COMMON_LIBS) \
$(NULL)
+gdm_disable_wayland_LDADD = \
+ $(COMMON_LIBS) \
+ $(NULL)
+
+gdm_disable_wayland_SOURCES = \
+ gdm-disable-wayland.c \
+ $(NULL)
+
CLEANFILES = \
$(NULL)
DISTCLEANFILES = \
$(NULL)
diff --git a/utils/gdm-disable-wayland.c b/utils/gdm-disable-wayland.c
new file mode 100644
index 000000000..be61c4d8f
--- /dev/null
+++ b/utils/gdm-disable-wayland.c
@@ -0,0 +1,53 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2018 Red Hat, Inc.
+ *
+ * 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 <locale.h>
+#include <stdlib.h>
+#include <sysexits.h>
+
+#include <glib.h>
+
+int
+main (int argc, char *argv[])
+{
+ g_autoptr(GKeyFile) key_file = NULL;
+ g_autoptr(GError) error = NULL;
+ gboolean saved_okay;
+
+ setlocale (LC_ALL, "");
+
+ key_file = g_key_file_new ();
+
+ g_key_file_set_boolean (key_file, "daemon", "WaylandEnable", FALSE);
+
+ g_mkdir_with_parents (GDM_RUN_DIR, 0711);
+
+ saved_okay = g_key_file_save_to_file (key_file, GDM_RUNTIME_CONF, &error);
+
+ if (!saved_okay) {
+ g_printerr ("gdm-disable-wayland: unable to disable wayland: %s",
+ error->message);
+ return EX_CANTCREAT;
+ }
+
+ return EX_OK;
+}
--
2.17.1

View File

@ -1,4 +1,4 @@
From a45b3f26e1f1f4ffc8870ebf073698d5eecf587b Mon Sep 17 00:00:00 2001
From 70eb29d5eedc2b66e617745be1dd145aac3e177e Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 15 Aug 2018 10:48:16 -0400
Subject: [PATCH 1/4] worker: don't load user settings for program sessions
@ -6,14 +6,14 @@ Subject: [PATCH 1/4] worker: don't load user settings for program sessions
We don't need or want the login greeter to access accountsservice
for its session name
---
daemon/gdm-session-worker.c | 38 +++++++++++++++++++++++++------------
1 file changed, 26 insertions(+), 12 deletions(-)
daemon/gdm-session-worker.c | 37 ++++++++++++++++++++++++++-----------
1 file changed, 26 insertions(+), 11 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index c1d89cab2..e79073996 100644
index 774298b9..88fe36c1 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -409,103 +409,108 @@ gdm_session_execute (const char *file,
@@ -400,103 +400,108 @@ gdm_session_execute (const char *file,
*/
static gboolean
gdm_session_worker_get_username (GdmSessionWorker *worker,
@ -124,12 +124,12 @@ index c1d89cab2..e79073996 100644
worker->priv->service,
question,
answerp,
@@ -2475,87 +2480,89 @@ gdm_session_worker_get_property (GObject *object,
g_value_set_string (value, self->priv->server_address);
break;
case PROP_IS_REAUTH_SESSION:
@@ -2600,87 +2605,89 @@ gdm_session_worker_get_property (GObject *object,
g_value_set_boolean (value, self->priv->is_reauth_session);
break;
case PROP_STATE:
g_value_set_enum (value, self->priv->state);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -218,7 +218,8 @@ index c1d89cab2..e79073996 100644
g_free (session_name);
}
@@ -2634,109 +2641,111 @@ do_authorize (GdmSessionWorker *worker)
@@ -2758,110 +2765,113 @@ do_authorize (GdmSessionWorker *worker)
g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
}
worker->priv->pending_invocation = NULL;
}
@ -248,7 +249,8 @@ index c1d89cab2..e79073996 100644
g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED);
g_debug ("GdmSessionWorker: saving account details for user %s", worker->priv->username);
worker->priv->state = GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED;
+
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
- if (!gdm_session_settings_save (worker->priv->user_settings,
- worker->priv->username)) {
- g_warning ("could not save session and language settings");
@ -334,7 +336,7 @@ index c1d89cab2..e79073996 100644
}
gdm_dbus_worker_complete_open (GDM_DBUS_WORKER (worker), worker->priv->pending_invocation, session_id);
@@ -2980,155 +2989,161 @@ gdm_session_worker_handle_initialize (GdmDBusWorker *object,
@@ -3105,155 +3115,161 @@ gdm_session_worker_handle_initialize (GdmDBusWorker *object,
if (g_strcmp0 (key, "service") == 0) {
worker->priv->service = g_variant_dup_string (value, NULL);
} else if (g_strcmp0 (key, "extensions") == 0) {
@ -496,7 +498,7 @@ index c1d89cab2..e79073996 100644
GDBusMethodInvocation *invocation,
const char *service,
const char *username,
@@ -3459,98 +3474,97 @@ static void
@@ -3591,61 +3607,60 @@ static void
reauthentication_request_free (ReauthenticationRequest *request)
{
@ -558,44 +560,6 @@ index c1d89cab2..e79073996 100644
g_return_if_fail (worker->priv != NULL);
gdm_session_worker_unwatch_child (worker);
if (worker->priv->child_pid > 0) {
gdm_signal_pid (worker->priv->child_pid, SIGTERM);
gdm_wait_on_pid (worker->priv->child_pid);
}
- g_object_unref (worker->priv->user_settings);
+ g_clear_object (&worker->priv->user_settings);
g_free (worker->priv->service);
g_free (worker->priv->x11_display_name);
g_free (worker->priv->x11_authority_file);
g_free (worker->priv->display_device);
g_free (worker->priv->display_seat_id);
g_free (worker->priv->hostname);
g_free (worker->priv->username);
g_free (worker->priv->server_address);
g_strfreev (worker->priv->arguments);
g_strfreev (worker->priv->extensions);
g_hash_table_unref (worker->priv->reauthentication_requests);
G_OBJECT_CLASS (gdm_session_worker_parent_class)->finalize (object);
}
GdmSessionWorker *
gdm_session_worker_new (const char *address,
gboolean is_reauth_session)
{
GObject *object;
object = g_object_new (GDM_TYPE_SESSION_WORKER,
"server-address", address,
"is-reauth-session", is_reauth_session,
NULL);
return GDM_SESSION_WORKER (object);
}
--
2.17.1
2.27.0

View File

@ -1,7 +1,7 @@
From 84b823187c8e0b23274cd1a93f4e47a2c585c75b Mon Sep 17 00:00:00 2001
From 874b26e3674d540df37d7f145df853bcf81e5a26 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/2] gdm-x-session: run session bus on non-seat0 seats
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.
@ -9,14 +9,14 @@ 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 | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
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 a8263ba11..55637b378 100644
index 418240dc0..77d6b8ff0 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2846,130 +2846,139 @@ on_start_program_cb (GdmDBusWorker *worker,
@@ -2822,119 +2822,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;
@ -25,8 +25,8 @@ index a8263ba11..55637b378 100644
service_name = conversation->service_name;
if (worked) {
self->priv->session_pid = pid;
self->priv->session_conversation = conversation;
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);
@ -50,9 +50,10 @@ index a8263ba11..55637b378 100644
+ 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->priv->session_conversation == NULL);
g_return_if_fail (self->session_conversation == NULL);
conversation = find_conversation_by_name (self, service_name);
@ -67,7 +68,7 @@ index a8263ba11..55637b378 100644
display_mode = gdm_session_get_display_mode (self);
#ifdef ENABLE_WAYLAND_SUPPORT
is_x11 = g_strcmp0 (self->priv->session_type, "wayland") != 0;
is_x11 = g_strcmp0 (self->session_type, "wayland") != 0;
#endif
if (display_mode == GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED ||
@ -75,18 +76,20 @@ index a8263ba11..55637b378 100644
run_launcher = TRUE;
}
+ if (g_strcmp0 (self->priv->display_seat_id, "seat0") != 0 && !run_launcher) {
register_session = !gdm_session_session_registers (self);
+ if (g_strcmp0 (self->display_seat_id, "seat0") != 0 && !run_launcher) {
+ run_separate_bus = TRUE;
+ }
+
if (self->priv->selected_program == NULL) {
if (self->selected_program == NULL) {
gboolean run_xsession_script;
command = get_session_command (self);
run_xsession_script = !gdm_session_bypasses_xsession (self);
if (self->priv->display_is_local) {
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;
@ -96,70 +99,53 @@ index a8263ba11..55637b378 100644
if (run_launcher) {
if (is_x11) {
program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s %s\"%s\"",
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\"",
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);
+ }
+ 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\"",
- self->priv->selected_program);
+ program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"",
+ self->priv->selected_program);
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\"",
self->priv->selected_program);
program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"dbus-run-session -- %s\"",
register_session ? "--register-session " : "",
self->selected_program);
}
} else {
- if (g_strcmp0 (self->priv->display_seat_id, "seat0") != 0) {
+ if (run_separate_bus) {
program = g_strdup_printf ("dbus-run-session -- %s",
self->priv->selected_program);
} else {
program = g_strdup (self->priv->selected_program);
}
}
}
set_up_session_environment (self);
send_environment (self, conversation);
gdm_dbus_worker_call_start_program (conversation->worker_proxy,
program,
conversation->worker_cancellable,
(GAsyncReadyCallback) on_start_program_cb,
conversation);
g_free (program);
}
static void
stop_all_conversations (GdmSession *self)
{
stop_all_other_conversations (self, NULL, TRUE);
}
static void
do_reset (GdmSession *self)
{
stop_all_conversations (self);
--
2.21.1
2.30.1

View File

@ -0,0 +1,131 @@
From 677d370e892788635c4086b139d78499510fa86c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 20 Jul 2021 13:36:45 -0400
Subject: [PATCH 2/2] libgdm: Sort session list
Right now the session list comes out in hash table order.
This commit changes the code to sort by description.
---
libgdm/gdm-sessions.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/libgdm/gdm-sessions.c b/libgdm/gdm-sessions.c
index 97ed5ef3..f078e04b 100644
--- a/libgdm/gdm-sessions.c
+++ b/libgdm/gdm-sessions.c
@@ -311,92 +311,111 @@ collect_sessions (void)
g_ptr_array_add (wayland_search_array, g_strdup (wayland_search_dirs[i]));
}
#endif
if (gdm_available_sessions_map == NULL) {
gdm_available_sessions_map = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify)gdm_session_file_free);
}
if (!supported_session_types || g_strv_contains ((const char * const *) supported_session_types, "x11")) {
for (i = 0; i < xorg_search_array->len; i++) {
collect_sessions_from_directory (g_ptr_array_index (xorg_search_array, i));
}
}
#ifdef ENABLE_WAYLAND_SUPPORT
#ifdef ENABLE_USER_DISPLAY_SERVER
if (!supported_session_types || g_strv_contains ((const char * const *) supported_session_types, "wayland")) {
for (i = 0; i < wayland_search_array->len; i++) {
collect_sessions_from_directory (g_ptr_array_index (wayland_search_array, i));
}
}
#endif
#endif
g_hash_table_foreach_remove (gdm_available_sessions_map,
remove_duplicate_sessions,
names_seen_before);
}
+static gint
+compare_session_ids (gconstpointer a,
+ gconstpointer b)
+{
+ GdmSessionFile *session_a, *session_b;
+ session_a = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, a);
+ session_b = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map, b);
+
+ if (session_a == NULL)
+ return -1;
+
+ if (session_b == NULL)
+ return 1;
+
+ return g_strcmp0 (session_a->translated_name, session_b->translated_name);
+}
+
/**
* gdm_get_session_ids:
*
* Reads /usr/share/xsessions and other relevant places for possible sessions
* to log into and returns the complete list.
*
* Returns: (transfer full): a %NULL terminated list of session ids
*/
char **
gdm_get_session_ids (void)
{
GHashTableIter iter;
gpointer key, value;
GPtrArray *array;
if (!gdm_sessions_map_is_initialized) {
collect_sessions ();
gdm_sessions_map_is_initialized = TRUE;
}
array = g_ptr_array_new ();
g_hash_table_iter_init (&iter, gdm_available_sessions_map);
while (g_hash_table_iter_next (&iter, &key, &value)) {
GdmSessionFile *session;
session = (GdmSessionFile *) value;
g_ptr_array_add (array, g_strdup (session->id));
}
g_ptr_array_add (array, NULL);
+ g_ptr_array_sort (array, compare_session_ids);
+
return (char **) g_ptr_array_free (array, FALSE);
}
/**
* gdm_get_session_name_and_description:
* @id: an id from gdm_get_session_ids()
* @description: (out): optional returned session description
*
* Takes an xsession id and returns the name and comment about it.
*
* Returns: The session name if found, or %NULL otherwise
*/
char *
gdm_get_session_name_and_description (const char *id,
char **description)
{
GdmSessionFile *session;
char *name;
if (!gdm_sessions_map_is_initialized) {
collect_sessions ();
gdm_sessions_map_is_initialized = TRUE;
}
session = (GdmSessionFile *) g_hash_table_lookup (gdm_available_sessions_map,
id);
if (session == NULL) {
return NULL;
--
2.27.0

View File

@ -1,164 +0,0 @@
From 417f0aed42959719c40f0f8ec65050dcf2510bd1 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 16 May 2018 14:10:34 +0100
Subject: [PATCH 02/51] local-display-factory: Add
gdm_local_display_factory_use_wayland() helper
Factor out the code which decides if Xorg or Wayland should be used into
a helper function.
---
daemon/gdm-local-display-factory.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 1a9196ee1..b21e3aee0 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -158,60 +158,73 @@ take_next_display_number (GdmLocalDisplayFactory *factory)
ret = num + 1;
break;
}
}
out:
/* now reserve this number */
g_debug ("GdmLocalDisplayFactory: Reserving X display: %u", ret);
g_hash_table_insert (factory->priv->used_display_numbers, GUINT_TO_POINTER (ret), NULL);
return ret;
}
static void
on_display_disposed (GdmLocalDisplayFactory *factory,
GdmDisplay *display)
{
g_debug ("GdmLocalDisplayFactory: Display %p disposed", display);
}
static void
store_display (GdmLocalDisplayFactory *factory,
GdmDisplay *display)
{
GdmDisplayStore *store;
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
gdm_display_store_add (store, display);
}
+static gboolean
+gdm_local_display_factory_use_wayland (void)
+{
+#ifdef ENABLE_WAYLAND_SUPPORT
+ gboolean wayland_enabled = FALSE;
+ if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
+ if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
+ return TRUE;
+ }
+#endif
+ return FALSE;
+}
+
/*
Example:
dbus-send --system --dest=org.gnome.DisplayManager \
--type=method_call --print-reply --reply-timeout=2000 \
/org/gnome/DisplayManager/Manager \
org.gnome.DisplayManager.Manager.GetDisplays
*/
gboolean
gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
char **id,
GError **error)
{
gboolean ret;
GdmDisplay *display = NULL;
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
ret = FALSE;
g_debug ("GdmLocalDisplayFactory: Creating transient display");
#ifdef ENABLE_USER_DISPLAY_SERVER
display = gdm_local_display_new ();
#else
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
@@ -422,68 +435,62 @@ gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
GVariant *array;
GVariantIter iter;
const char *seat;
result = g_dbus_connection_call_sync (factory->priv->connection,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ListSeats",
NULL,
G_VARIANT_TYPE ("(a(so))"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, &error);
if (!result) {
g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error->message);
g_clear_error (&error);
return FALSE;
}
array = g_variant_get_child_value (result, 0);
g_variant_iter_init (&iter, array);
while (g_variant_iter_loop (&iter, "(&so)", &seat, NULL)) {
gboolean is_initial;
const char *session_type = NULL;
if (g_strcmp0 (seat, "seat0") == 0) {
is_initial = TRUE;
-#ifdef ENABLE_WAYLAND_SUPPORT
- gboolean wayland_enabled = FALSE;
- if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
- if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) ) {
- session_type = "wayland";
- }
- }
-#endif
+ if (gdm_local_display_factory_use_wayland ())
+ session_type = "wayland";
} else {
is_initial = FALSE;
}
create_display (factory, seat, session_type, is_initial);
}
g_variant_unref (result);
g_variant_unref (array);
return TRUE;
}
static void
on_seat_new (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *seat;
g_variant_get (parameters, "(&s&o)", &seat, NULL);
create_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat, NULL, FALSE);
}
static void
on_seat_removed (GDBusConnection *connection,
const gchar *sender_name,
--
2.27.0

View File

@ -1,87 +0,0 @@
From aeb88313c2110389ec530c8c7d5d816bac24d254 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Sep 2020 00:41:00 -0400
Subject: [PATCH 2/3] session: Don't leak remote greeter interface
XDMCP login screens get a "Remote Geeter Interface" exported over
the bus connection (so the login window can provide a Disconnect
button).
This interface is getting leaked when the session object is disposed,
leaving the bus connection itself undisposed, which causes an fd
leak.
This commit plugs the interface leak, and thus the fd leak.
---
daemon/gdm-session.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 540a2534d..d6d8f128a 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -3602,60 +3602,61 @@ gdm_session_get_property (GObject *object,
break;
#ifdef ENABLE_WAYLAND_SUPPORT
case PROP_IGNORE_WAYLAND:
g_value_set_boolean (value, self->priv->ignore_wayland);
break;
#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_session_dispose (GObject *object)
{
GdmSession *self;
self = GDM_SESSION (object);
g_debug ("GdmSession: Disposing session");
gdm_session_close (self);
g_clear_pointer (&self->priv->conversations,
g_hash_table_unref);
g_clear_object (&self->priv->user_verifier_interface);
g_clear_pointer (&self->priv->user_verifier_extensions,
g_hash_table_unref);
g_clear_object (&self->priv->greeter_interface);
+ g_clear_object (&self->priv->remote_greeter_interface);
g_clear_object (&self->priv->chooser_interface);
g_free (self->priv->display_name);
self->priv->display_name = NULL;
g_free (self->priv->display_hostname);
self->priv->display_hostname = NULL;
g_free (self->priv->display_device);
self->priv->display_device = NULL;
g_free (self->priv->display_seat_id);
self->priv->display_seat_id = NULL;
g_free (self->priv->display_x11_authority_file);
self->priv->display_x11_authority_file = NULL;
g_strfreev (self->priv->conversation_environment);
self->priv->conversation_environment = NULL;
if (self->priv->worker_server != NULL) {
g_dbus_server_stop (self->priv->worker_server);
g_clear_object (&self->priv->worker_server);
}
if (self->priv->outside_server != NULL) {
g_dbus_server_stop (self->priv->outside_server);
g_clear_object (&self->priv->outside_server);
}
--
2.26.2

View File

@ -1,4 +1,4 @@
From e625a214d531635db1e48b2dc51ed0e09ef8005b Mon Sep 17 00:00:00 2001
From 96e78f519a4d5ce2e5b708035ae1f43eb7c1bbd2 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 14 Aug 2018 14:52:41 -0400
Subject: [PATCH 2/4] session: support new accountsservice Session and
@ -12,15 +12,15 @@ a related "SessionType" property to replace "XSession".
This commit switches GDM over to use the new properties.
---
daemon/gdm-session-settings.c | 61 ++++++++++++++++++++++++---
daemon/gdm-session-settings.c | 61 ++++++++++++++++++++++--
daemon/gdm-session-settings.h | 3 ++
daemon/gdm-session-worker.c | 28 +++++++++++++
daemon/gdm-session-worker.c | 28 +++++++++++
daemon/gdm-session-worker.xml | 3 ++
daemon/gdm-session.c | 78 ++++++++++++++++++++++++++---------
5 files changed, 148 insertions(+), 25 deletions(-)
daemon/gdm-session.c | 87 +++++++++++++++++++++++++----------
5 files changed, 153 insertions(+), 29 deletions(-)
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
index 933f095bc..8463fad32 100644
index 484a3b5b..f2b1addd 100644
--- a/daemon/gdm-session-settings.c
+++ b/daemon/gdm-session-settings.c
@@ -12,114 +12,121 @@
@ -79,7 +79,9 @@ index 933f095bc..8463fad32 100644
PROP_IS_LOADED
};
G_DEFINE_TYPE (GdmSessionSettings, gdm_session_settings, G_TYPE_OBJECT)
G_DEFINE_TYPE_WITH_PRIVATE (GdmSessionSettings,
gdm_session_settings,
G_TYPE_OBJECT)
static void
gdm_session_settings_class_init (GdmSessionSettingsClass *settings_class)
@ -91,8 +93,6 @@ index 933f095bc..8463fad32 100644
object_class->finalize = gdm_session_settings_finalize;
gdm_session_settings_class_install_properties (settings_class);
g_type_class_add_private (settings_class, sizeof (GdmSessionSettingsPrivate));
}
static void
@ -107,7 +107,7 @@ index 933f095bc..8463fad32 100644
param_spec = g_param_spec_string ("session-name", "Session Name",
"The name of the session",
NULL, G_PARAM_READWRITE);
NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_SESSION_NAME, param_spec);
+ param_spec = g_param_spec_string ("session-type", "Session Type",
@ -118,11 +118,11 @@ index 933f095bc..8463fad32 100644
param_spec = g_param_spec_string ("language-name", "Language Name",
"The name of the language",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_LANGUAGE_NAME, param_spec);
param_spec = g_param_spec_boolean ("is-loaded", NULL, NULL,
FALSE, G_PARAM_READABLE);
FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_IS_LOADED, param_spec);
}
@ -305,14 +305,14 @@ index 933f095bc..8463fad32 100644
- session_name = act_user_get_x_session (settings->priv->user);
- g_debug ("GdmSessionSettings: saved session is %s", session_name);
+ /* 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;
- if (session_name != NULL) {
+
+
+
+ session_type = act_user_get_session_type (settings->priv->user);
+ session_name = act_user_get_session (settings->priv->user);
- if (session_name != NULL) {
+
+ g_debug ("GdmSessionSettings: saved session is %s (type %s)", session_name, session_type);
+
+ if (session_type != NULL && session_type[0] != '\0') {
@ -409,7 +409,7 @@ index 933f095bc..8463fad32 100644
return TRUE;
}
diff --git a/daemon/gdm-session-settings.h b/daemon/gdm-session-settings.h
index 20946bff1..db38ffc72 100644
index 20946bff..db38ffc7 100644
--- a/daemon/gdm-session-settings.h
+++ b/daemon/gdm-session-settings.h
@@ -33,37 +33,40 @@ G_BEGIN_DECLS
@ -454,10 +454,10 @@ index 20946bff1..db38ffc72 100644
G_END_DECLS
#endif /* GDM_SESSION_SETTINGS_H */
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index e79073996..ae86d28ac 100644
index 88fe36c1..c1201b70 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -2539,60 +2539,74 @@ gdm_session_worker_handle_set_language_name (GdmDBusWorker *object,
@@ -2664,60 +2664,74 @@ gdm_session_worker_handle_set_language_name (GdmDBusWorker *object,
gdm_dbus_worker_complete_set_language_name (object, invocation);
return TRUE;
}
@ -532,7 +532,7 @@ index e79073996..ae86d28ac 100644
static void
do_authenticate (GdmSessionWorker *worker)
{
@@ -3001,158 +3015,172 @@ gdm_session_worker_handle_initialize (GdmDBusWorker *object,
@@ -3127,158 +3141,172 @@ gdm_session_worker_handle_initialize (GdmDBusWorker *object,
} else if (g_strcmp0 (key, "x11-authority-file") == 0) {
worker->priv->x11_authority_file = g_variant_dup_string (value, NULL);
} else if (g_strcmp0 (key, "console") == 0) {
@ -706,7 +706,7 @@ index e79073996..ae86d28ac 100644
const char *log_file)
{
diff --git a/daemon/gdm-session-worker.xml b/daemon/gdm-session-worker.xml
index 4280fe095..a215779c8 100644
index 4280fe09..a215779c 100644
--- a/daemon/gdm-session-worker.xml
+++ b/daemon/gdm-session-worker.xml
@@ -51,40 +51,43 @@
@ -754,12 +754,10 @@ index 4280fe095..a215779c8 100644
</interface>
</node>
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 19d26c92e..e6640aac7 100644
index 29459346..43da024f 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -59,60 +59,61 @@
#define GDM_SESSION_DBUS_ERROR_CANCEL "org.gnome.DisplayManager.Session.Error.Cancel"
@@ -61,60 +61,61 @@
#define GDM_SESSION_DBUS_OBJECT_PATH "/org/gnome/DisplayManager/Session"
#define GDM_WORKER_DBUS_PATH "/org/gnome/DisplayManager/Worker"
@ -782,8 +780,10 @@ index 19d26c92e..e6640aac7 100644
GPid reauth_pid_of_caller;
} GdmSessionConversation;
struct _GdmSessionPrivate
struct _GdmSession
{
GObject parent;
/* per open scope */
char *selected_program;
char *selected_session;
@ -819,25 +819,14 @@ index 19d26c92e..e6640aac7 100644
char *display_name;
char *display_hostname;
char *display_device;
@@ -312,295 +313,310 @@ on_establish_credentials_cb (GdmDBusWorker *proxy,
return;
self = g_object_ref (conversation->session);
service_name = g_strdup (conversation->service_name);
if (worked) {
if (self->priv->user_verifier_interface != NULL) {
gdm_dbus_user_verifier_emit_verification_complete (self->priv->user_verifier_interface,
service_name);
g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name);
}
switch (self->priv->verification_mode) {
case GDM_SESSION_VERIFICATION_MODE_LOGIN:
case GDM_SESSION_VERIFICATION_MODE_CHOOSER:
gdm_session_open_session (self, service_name);
break;
@@ -328,309 +329,325 @@ on_establish_credentials_cb (GdmDBusWorker *proxy,
case GDM_SESSION_VERIFICATION_MODE_REAUTHENTICATE:
if (self->user_verifier_interface != NULL) {
gdm_dbus_user_verifier_emit_verification_complete (self->user_verifier_interface,
service_name);
g_signal_emit (self, signals[VERIFICATION_COMPLETE], 0, service_name);
}
break;
default:
break;
}
@ -849,6 +838,17 @@ index 19d26c92e..e6640aac7 100644
g_object_unref (self);
}
static gboolean
supports_session_type (GdmSession *self,
const char *session_type)
{
if (session_type == NULL)
return TRUE;
return g_strv_contains ((const char * const *) self->supported_session_types,
session_type);
}
static char **
-get_system_session_dirs (GdmSession *self)
+get_system_session_dirs (GdmSession *self,
@ -856,6 +856,8 @@ index 19d26c92e..e6640aac7 100644
{
GArray *search_array = NULL;
char **search_dirs;
int i, j;
const gchar * const *system_data_dirs = g_get_system_data_dirs ();
static const char *x_search_dirs[] = {
"/etc/X11/sessions/",
@ -868,20 +870,33 @@ index 19d26c92e..e6640aac7 100644
search_array = g_array_new (TRUE, TRUE, sizeof (char *));
- g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
+ if (type == NULL || strcmp (type, "x11") == 0)
+ g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
for (j = 0; self->supported_session_types[j] != NULL; j++) {
const char *supported_type = self->supported_session_types[j];
- if (g_str_equal (supported_type, "x11")) {
+ if (g_str_equal (supported_type, "x11") ||
+ (type == NULL || g_str_equal (type, supported_type))) {
for (i = 0; system_data_dirs[i]; i++) {
gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
g_array_append_val (search_array, dir);
}
g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
}
#ifdef ENABLE_WAYLAND_SUPPORT
- if (!self->priv->ignore_wayland) {
+ if ((!self->priv->ignore_wayland && type == NULL) || g_strcmp0 (type, "wayland") == 0) {
#ifdef ENABLE_USER_DISPLAY_SERVER
g_array_prepend_val (search_array, wayland_search_dir);
#else
g_array_append_val (search_array, wayland_search_dir);
- if (g_str_equal (supported_type, "wayland")) {
+ if (g_str_equal (supported_type, "wayland") ||
+ (type == NULL || g_str_equal (type, supported_type))) {
for (i = 0; system_data_dirs[i]; i++) {
gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
g_array_append_val (search_array, dir);
}
g_array_append_val (search_array, wayland_search_dir);
}
#endif
}
#endif
search_dirs = g_strdupv ((char **) search_array->data);
@ -961,9 +976,9 @@ index 19d26c92e..e6640aac7 100644
*command = NULL;
}
+ if (self->priv->ignore_wayland && g_strcmp0 (type, "wayland") == 0) {
+ g_debug ("GdmSession: ignoring wayland session command request for file '%s'",
+ file);
+ if (!supports_session_type (self, type)) {
+ g_debug ("GdmSession: ignoring %s session command request for file '%s'",
+ type, file);
+ goto out;
+ }
+
@ -1046,11 +1061,11 @@ index 19d26c92e..e6640aac7 100644
{
const char *default_language;
if (self->priv->saved_language != NULL) {
return self->priv->saved_language;
if (self->saved_language != NULL) {
return self->saved_language;
}
default_language = g_hash_table_lookup (self->priv->environment,
default_language = g_hash_table_lookup (self->environment,
"LANG");
if (default_language != NULL) {
@ -1069,10 +1084,10 @@ index 19d26c92e..e6640aac7 100644
GSequence *sessions;
GSequenceIter *session;
if (self->priv->fallback_session_name != NULL) {
if (self->fallback_session_name != NULL) {
/* verify that the cached version still exists */
- if (get_session_command_for_name (self, self->priv->fallback_session_name, NULL)) {
+ if (get_session_command_for_name (self, self->priv->fallback_session_name, NULL, NULL)) {
- if (get_session_command_for_name (self, self->fallback_session_name, NULL)) {
+ if (get_session_command_for_name (self, self->fallback_session_name, NULL, NULL)) {
goto out;
}
}
@ -1080,8 +1095,8 @@ index 19d26c92e..e6640aac7 100644
name = g_strdup ("gnome");
- if (get_session_command_for_name (self, name, NULL)) {
+ if (get_session_command_for_name (self, name, NULL, NULL)) {
g_free (self->priv->fallback_session_name);
self->priv->fallback_session_name = name;
g_free (self->fallback_session_name);
self->fallback_session_name = name;
goto out;
}
g_free (name);
@ -1136,27 +1151,24 @@ index 19d26c92e..e6640aac7 100644
session = g_sequence_iter_next (session);
} while (!g_sequence_iter_is_end (session));
g_free (self->priv->fallback_session_name);
self->priv->fallback_session_name = g_strdup (name);
g_free (self->fallback_session_name);
self->fallback_session_name = g_strdup (name);
g_sequence_free (sessions);
out:
return self->priv->fallback_session_name;
@@ -616,60 +632,63 @@ get_default_session_name (GdmSession *self)
return get_fallback_session_name (self);
}
return self->fallback_session_name;
@@ -649,60 +666,63 @@ get_default_session_name (GdmSession *self)
static void
gdm_session_defaults_changed (GdmSession *self)
{
update_session_type (self);
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_language_name_changed (self->priv->greeter_interface,
if (self->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_language_name_changed (self->greeter_interface,
get_default_language_name (self));
gdm_dbus_greeter_emit_default_session_name_changed (self->priv->greeter_interface,
gdm_dbus_greeter_emit_default_session_name_changed (self->greeter_interface,
get_default_session_name (self));
}
}
@ -1166,19 +1178,22 @@ index 19d26c92e..e6640aac7 100644
const char *text)
{
g_debug ("GdmSession: Setting user: '%s'", text);
g_debug ("GdmSession: selecting user '%s' for session '%s' (%p)",
text,
gdm_session_get_session_id (self),
self);
g_free (self->priv->selected_user);
self->priv->selected_user = g_strdup (text);
g_free (self->selected_user);
self->selected_user = g_strdup (text);
g_free (self->priv->saved_session);
self->priv->saved_session = NULL;
g_free (self->saved_session);
self->saved_session = NULL;
+ g_free (self->priv->saved_session_type);
+ self->priv->saved_session_type = NULL;
+ g_free (self->saved_session_type);
+ self->saved_session_type = NULL;
+
g_free (self->priv->saved_language);
self->priv->saved_language = NULL;
g_free (self->saved_language);
self->saved_language = NULL;
}
static void
@ -1207,7 +1222,7 @@ index 19d26c92e..e6640aac7 100644
static void
set_pending_query (GdmSessionConversation *conversation,
@@ -936,80 +955,91 @@ worker_on_reauthenticated (GdmDBusWorker *worker,
@@ -969,83 +989,94 @@ worker_on_reauthenticated (GdmDBusWorker *worker,
GdmSession *self = conversation->session;
g_debug ("GdmSession: Emitting 'reauthenticated' signal ");
g_signal_emit (self, signals[REAUTHENTICATED], 0, service_name);
@ -1221,11 +1236,11 @@ index 19d26c92e..e6640aac7 100644
GdmSession *self = conversation->session;
if (strlen (language_name) > 0) {
g_free (self->priv->saved_language);
self->priv->saved_language = g_strdup (language_name);
g_free (self->saved_language);
self->saved_language = g_strdup (language_name);
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_language_name_changed (self->priv->greeter_interface,
if (self->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_language_name_changed (self->greeter_interface,
language_name);
}
}
@ -1239,24 +1254,27 @@ index 19d26c92e..e6640aac7 100644
GdmSession *self = conversation->session;
- if (! get_session_command_for_name (self, session_name, NULL)) {
+ if (! get_session_command_for_name (self, session_name, self->priv->saved_session_type, NULL)) {
+ 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->priv->saved_session);
self->priv->saved_session = NULL;
} else if (strcmp (session_name,
get_default_session_name (self)) != 0) {
g_free (self->priv->saved_session);
self->priv->saved_session = g_strdup (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->priv->greeter_interface != NULL) {
gdm_dbus_greeter_emit_default_session_name_changed (self->priv->greeter_interface,
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
@ -1266,8 +1284,8 @@ index 19d26c92e..e6640aac7 100644
+{
+ GdmSession *self = conversation->session;
+
+ g_free (self->priv->saved_session_type);
+ self->priv->saved_session_type = g_strdup (session_type);
+ g_free (self->saved_session_type);
+ self->saved_session_type = g_strdup (session_type);
+}
+
static GdmSessionConversation *
@ -1277,7 +1295,7 @@ index 19d26c92e..e6640aac7 100644
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, self->priv->conversations);
g_hash_table_iter_init (&iter, self->conversations);
while (g_hash_table_iter_next (&iter, &key, &value)) {
GdmSessionConversation *conversation;
@ -1300,7 +1318,7 @@ index 19d26c92e..e6640aac7 100644
uid_t connecting_user;
connecting_user = g_credentials_get_unix_user (credentials, NULL);
@@ -1089,60 +1119,63 @@ register_worker (GdmDBusWorkerManager *worker_manager_interface,
@@ -1125,60 +1156,63 @@ register_worker (GdmDBusWorkerManager *worker_manager_interface,
g_dbus_method_invocation_return_value (invocation, NULL);
conversation->worker_proxy = gdm_dbus_worker_proxy_new_sync (connection,
@ -1344,8 +1362,8 @@ index 19d26c92e..e6640aac7 100644
g_debug ("GdmSession: Emitting conversation-started signal");
g_signal_emit (self, signals[CONVERSATION_STARTED], 0, conversation->service_name);
if (self->priv->user_verifier_interface != NULL) {
gdm_dbus_user_verifier_emit_conversation_started (self->priv->user_verifier_interface,
if (self->user_verifier_interface != NULL) {
gdm_dbus_user_verifier_emit_conversation_started (self->user_verifier_interface,
conversation->service_name);
}
@ -1364,9 +1382,9 @@ index 19d26c92e..e6640aac7 100644
g_debug ("GdmSession: Conversation started");
return TRUE;
@@ -1804,60 +1837,63 @@ static void
free_conversation (GdmSessionConversation *conversation)
{
@@ -1921,60 +1955,63 @@ free_conversation (GdmSessionConversation *conversation)
close_conversation (conversation);
if (conversation->job != NULL) {
g_warning ("Freeing conversation '%s' with active job", conversation->service_name);
}
@ -1428,7 +1446,7 @@ index 19d26c92e..e6640aac7 100644
error = NULL;
if (!g_file_get_contents (config_file, &contents, &length, &error)) {
g_debug ("Failed to parse '%s': %s",
@@ -2412,83 +2448,83 @@ gdm_session_send_environment (GdmSession *self,
@@ -2533,83 +2570,83 @@ gdm_session_send_environment (GdmSession *self,
g_return_if_fail (GDM_IS_SESSION (self));
conversation = find_conversation_by_name (self, service_name);
@ -1442,8 +1460,8 @@ index 19d26c92e..e6640aac7 100644
{
/* FIXME: test the session names before we use them? */
if (self->priv->selected_session != NULL) {
return self->priv->selected_session;
if (self->selected_session != NULL) {
return self->selected_session;
}
return get_default_session_name (self);
@ -1476,7 +1494,7 @@ index 19d26c92e..e6640aac7 100644
GKeyFile *keyfile;
gchar *desktop_names = NULL;
if (self->priv->selected_program != NULL) {
if (self->selected_program != NULL) {
return g_strdup ("GNOME-Greeter:GNOME");
}
@ -1509,13 +1527,12 @@ index 19d26c92e..e6640aac7 100644
g_return_if_fail (key != NULL);
g_return_if_fail (value != NULL);
g_hash_table_replace (self->priv->environment,
g_hash_table_replace (self->environment,
g_strdup (key),
g_strdup (value));
}
@@ -3008,115 +3044,117 @@ gdm_session_get_conversation_session_id (GdmSession *self,
@@ -3179,148 +3216,150 @@ gdm_session_get_conversation_session_id (GdmSession *self,
conversation = find_conversation_by_name (self, service_name);
if (conversation == NULL) {
@ -1545,11 +1562,16 @@ index 19d26c92e..e6640aac7 100644
filename = get_session_filename (self);
- key_file = load_key_file_for_file (self, filename, &full_path);
+ key_file = load_key_file_for_file (self, filename, "wayland", &full_path);
if (supports_session_type (self, "wayland")) {
- key_file = load_key_file_for_file (self, filename, &full_path);
+ key_file = load_key_file_for_file (self, filename, NULL, &full_path);
if (key_file == NULL) {
goto out;
- if (key_file == NULL) {
- goto out;
- }
+ if (key_file == NULL) {
+ goto out;
+ }
}
if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
@ -1558,7 +1580,7 @@ index 19d26c92e..e6640aac7 100644
g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
out:
g_clear_pointer (&key_file, (GDestroyNotify) g_key_file_free);
g_clear_pointer (&key_file, g_key_file_free);
g_free (filename);
return is_wayland_session;
}
@ -1571,7 +1593,7 @@ index 19d26c92e..e6640aac7 100644
- gboolean is_wayland_session;
+ gboolean is_wayland_session = FALSE;
+
+ if (!self->priv->ignore_wayland)
+ if (supports_session_type (self, "wayland"))
+ is_wayland_session = gdm_session_is_wayland_session (self);
- is_wayland_session = gdm_session_is_wayland_session (self);
@ -1583,6 +1605,39 @@ index 19d26c92e..e6640aac7 100644
#endif
}
gboolean
gdm_session_session_registers (GdmSession *self)
{
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) key_file = NULL;
gboolean session_registers = FALSE;
g_autofree char *filename = NULL;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
filename = get_session_filename (self);
- key_file = load_key_file_for_file (self, filename, NULL);
+ key_file = load_key_file_for_file (self, filename, NULL, NULL);
session_registers = g_key_file_get_boolean (key_file,
G_KEY_FILE_DESKTOP_GROUP,
"X-GDM-SessionRegisters",
&error);
if (!session_registers &&
error != NULL &&
!g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
g_warning ("GdmSession: Couldn't read session file '%s'", filename);
return FALSE;
}
g_debug ("GdmSession: '%s' %s self", filename,
session_registers ? "registers" : "does not register");
return session_registers;
}
gboolean
gdm_session_bypasses_xsession (GdmSession *self)
{
@ -1632,10 +1687,10 @@ index 19d26c92e..e6640aac7 100644
gdm_session_get_display_mode (GdmSession *self)
{
g_debug ("GdmSession: type %s, program? %s, seat %s",
self->priv->session_type,
self->priv->is_program_session? "yes" : "no",
self->priv->display_seat_id);
self->session_type,
self->is_program_session? "yes" : "no",
self->display_seat_id);
--
2.17.1
2.27.0

View File

@ -1,922 +0,0 @@
From 4db5bf628396a7191f2392e7d09ab9bbd7c2b533 Mon Sep 17 00:00:00 2001
From: Xiaoguang Wang <xwang@suse.com>
Date: Thu, 16 May 2019 13:26:16 +0800
Subject: [PATCH 2/3] session-worker: kill user sessions when stop gdm service
At the moment the session worker exits as soon as it gets SIGTERM.
That means it may fail to stop the user session (which only happens
in the orderly shutdown path).
This commit sets up a SIGTERM handler that integrates with and
quits the main loop after the session is started.
It still retains the _exit-on-SIGTERM behavior before the session
is started, to ensure a stuck pam module doesn't prevent the
process from dying.
Some small changes to commit by Ray Strode.
Closes #400
---
daemon/gdm-session-worker.c | 39 +++++++++++++++++++++++++++---------
daemon/session-worker-main.c | 33 ++++++++++++++++++++++++++++++
2 files changed, 63 insertions(+), 9 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index f6935ab1d..aa288ac8e 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -159,60 +159,61 @@ struct GdmSessionWorkerPrivate
guint32 display_is_initial : 1;
guint state_change_idle_id;
GdmSessionDisplayMode display_mode;
char *server_address;
GDBusConnection *connection;
GdmDBusWorkerManager *manager;
GHashTable *reauthentication_requests;
GdmSessionAuditor *auditor;
GdmSessionSettings *user_settings;
GDBusMethodInvocation *pending_invocation;
};
#ifdef SUPPORTS_PAM_EXTENSIONS
static char gdm_pam_extension_environment_block[_POSIX_ARG_MAX];
static const char * const
gdm_supported_pam_extensions[] = {
GDM_PAM_EXTENSION_CHOICE_LIST,
NULL
};
#endif
enum {
PROP_0,
PROP_SERVER_ADDRESS,
PROP_IS_REAUTH_SESSION,
+ PROP_STATE,
};
static void gdm_session_worker_class_init (GdmSessionWorkerClass *klass);
static void gdm_session_worker_init (GdmSessionWorker *session_worker);
static void gdm_session_worker_finalize (GObject *object);
static void gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
const char *key,
const char *value);
static void queue_state_change (GdmSessionWorker *worker);
static void worker_interface_init (GdmDBusWorkerIface *iface);
typedef int (* GdmSessionWorkerPamNewMessagesFunc) (int,
const struct pam_message **,
struct pam_response **,
gpointer);
G_DEFINE_TYPE_WITH_CODE (GdmSessionWorker,
gdm_session_worker,
GDM_DBUS_TYPE_WORKER_SKELETON,
G_IMPLEMENT_INTERFACE (GDM_DBUS_TYPE_WORKER,
worker_interface_init))
/* adapted from glib script_execute */
static void
script_execute (const gchar *file,
char **argv,
@@ -971,100 +972,111 @@ jump_to_vt (GdmSessionWorker *worker,
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
}
/* It's possible that the current VT was left in a broken
* combination of states (KD_GRAPHICS with VT_AUTO), that
* can't be switched away from. This call makes sure things
* are set in a way that VT_ACTIVATE should work and
* VT_WAITACTIVE shouldn't hang.
*/
fix_terminal_vt_mode (worker, active_vt_tty_fd);
} else {
fd = active_vt_tty_fd;
}
handle_terminal_vt_switches (worker, fd);
if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
vt_number);
} else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
vt_number);
}
close (active_vt_tty_fd);
}
+static void
+gdm_session_worker_set_state (GdmSessionWorker *worker,
+ GdmSessionWorkerState state)
+{
+ if (worker->priv->state == state)
+ return;
+
+ worker->priv->state = state;
+ g_object_notify (G_OBJECT (worker), "state");
+}
+
static void
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
int status)
{
g_debug ("GdmSessionWorker: uninitializing PAM");
if (worker->priv->pam_handle == NULL)
return;
gdm_session_worker_get_username (worker, NULL);
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
pam_close_session (worker->priv->pam_handle, 0);
gdm_session_auditor_report_logout (worker->priv->auditor);
} else {
gdm_session_auditor_report_login_failure (worker->priv->auditor,
status,
pam_strerror (worker->priv->pam_handle, status));
}
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) {
pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED);
}
pam_end (worker->priv->pam_handle, status);
worker->priv->pam_handle = NULL;
gdm_session_worker_stop_auditor (worker);
if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
if (worker->priv->login_vt != worker->priv->session_vt) {
jump_to_vt (worker, worker->priv->login_vt);
}
}
worker->priv->login_vt = 0;
worker->priv->session_vt = 0;
g_debug ("GdmSessionWorker: state NONE");
- worker->priv->state = GDM_SESSION_WORKER_STATE_NONE;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE);
}
static char *
_get_tty_for_pam (const char *x11_display_name,
const char *display_device)
{
#ifdef __sun
return g_strdup (display_device);
#else
return g_strdup (x11_display_name);
#endif
}
#ifdef PAM_XAUTHDATA
static struct pam_xauth_data *
_get_xauth_for_pam (const char *x11_authority_file)
{
FILE *fh;
Xauth *auth = NULL;
struct pam_xauth_data *retval = NULL;
gsize len = sizeof (*retval) + 1;
fh = fopen (x11_authority_file, "r");
if (fh) {
auth = XauReadAuth (fh);
fclose (fh);
}
if (auth) {
len += auth->name_length + auth->data_length;
retval = g_malloc0 (len);
@@ -1173,61 +1185,61 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
goto out;
}
}
/* set RHOST */
if (hostname != NULL && hostname[0] != '\0') {
error_code = pam_set_item (worker->priv->pam_handle, PAM_RHOST, hostname);
g_debug ("error informing authentication system of user's hostname %s: %s",
hostname,
pam_strerror (worker->priv->pam_handle, error_code));
if (error_code != PAM_SUCCESS) {
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
"%s", "");
goto out;
}
}
/* set seat ID */
if (seat_id != NULL && seat_id[0] != '\0') {
gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
}
if (strcmp (service, "gdm-launch-environment") == 0) {
gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
}
g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
- worker->priv->state = GDM_SESSION_WORKER_STATE_SETUP_COMPLETE;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
/* Temporarily set PAM_TTY with the currently active VT (login screen)
PAM_TTY will be reset with the users VT right before the user session is opened */
ensure_login_vt (worker);
g_snprintf (tty_string, 256, "/dev/tty%d", worker->priv->login_vt);
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
if (!display_is_local)
worker->priv->password_is_required = TRUE;
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static gboolean
gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
gboolean password_is_required,
GError **error)
{
int error_code;
int authentication_flags;
g_debug ("GdmSessionWorker: authenticating user %s", worker->priv->username);
authentication_flags = 0;
@@ -1238,61 +1250,61 @@ gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
/* blocking call, does the actual conversation */
error_code = pam_authenticate (worker->priv->pam_handle, authentication_flags);
if (error_code == PAM_AUTHINFO_UNAVAIL) {
g_debug ("GdmSessionWorker: authentication service unavailable");
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_SERVICE_UNAVAILABLE,
"%s", "");
goto out;
} else if (error_code != PAM_SUCCESS) {
g_debug ("GdmSessionWorker: authentication returned %d: %s", error_code, pam_strerror (worker->priv->pam_handle, error_code));
/*
* Do not display a different message for user unknown versus
* a failed password for a valid user.
*/
if (error_code == PAM_USER_UNKNOWN) {
error_code = PAM_AUTH_ERR;
}
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
"%s", get_friendly_error_message (error_code));
goto out;
}
g_debug ("GdmSessionWorker: state AUTHENTICATED");
- worker->priv->state = GDM_SESSION_WORKER_STATE_AUTHENTICATED;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_AUTHENTICATED);
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static gboolean
gdm_session_worker_authorize_user (GdmSessionWorker *worker,
gboolean password_is_required,
GError **error)
{
int error_code;
int authentication_flags;
g_debug ("GdmSessionWorker: determining if authenticated user (password required:%d) is authorized to session",
password_is_required);
authentication_flags = 0;
if (password_is_required) {
authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK;
}
/* check that the account isn't disabled or expired
*/
error_code = pam_acct_mgmt (worker->priv->pam_handle, authentication_flags);
@@ -1303,61 +1315,61 @@ gdm_session_worker_authorize_user (GdmSessionWorker *worker,
g_debug ("GdmSessionWorker: authenticated user requires new auth token");
error_code = pam_chauthtok (worker->priv->pam_handle, PAM_CHANGE_EXPIRED_AUTHTOK);
gdm_session_worker_get_username (worker, NULL);
if (error_code != PAM_SUCCESS) {
gdm_session_auditor_report_password_change_failure (worker->priv->auditor);
} else {
gdm_session_auditor_report_password_changed (worker->priv->auditor);
}
}
/* If the user is reauthenticating, then authorization isn't required to
* proceed, the user is already logged in after all.
*/
if (worker->priv->is_reauth_session) {
error_code = PAM_SUCCESS;
}
if (error_code != PAM_SUCCESS) {
g_debug ("GdmSessionWorker: user is not authorized to log in: %s",
pam_strerror (worker->priv->pam_handle, error_code));
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_AUTHORIZING,
"%s", get_friendly_error_message (error_code));
goto out;
}
g_debug ("GdmSessionWorker: state AUTHORIZED");
- worker->priv->state = GDM_SESSION_WORKER_STATE_AUTHORIZED;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_AUTHORIZED);
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static void
gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
const char *key,
const char *value)
{
int error_code;
char *environment_entry;
if (value != NULL) {
environment_entry = g_strdup_printf ("%s=%s", key, value);
} else {
/* empty value means "remove from environment" */
environment_entry = g_strdup (key);
}
error_code = pam_putenv (worker->priv->pam_handle,
environment_entry);
if (error_code != PAM_SUCCESS) {
g_warning ("cannot put %s in pam environment: %s\n",
@@ -1716,61 +1728,61 @@ gdm_session_worker_accredit_user (GdmSessionWorker *worker,
/* If the user is reauthenticating and they've made it this far, then there
* is no reason we should lock them out of their session. They've already
* proved they are they same person who logged in, and that's all we care
* about.
*/
if (worker->priv->is_reauth_session) {
error_code = PAM_SUCCESS;
}
if (error_code != PAM_SUCCESS) {
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_GIVING_CREDENTIALS,
"%s",
pam_strerror (worker->priv->pam_handle, error_code));
goto out;
}
ret = TRUE;
out:
g_free (home);
g_free (shell);
if (ret) {
g_debug ("GdmSessionWorker: state ACCREDITED");
ret = TRUE;
gdm_session_worker_get_username (worker, NULL);
gdm_session_auditor_report_user_accredited (worker->priv->auditor);
- worker->priv->state = GDM_SESSION_WORKER_STATE_ACCREDITED;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCREDITED);
} else {
gdm_session_worker_uninitialize_pam (worker, error_code);
}
return ret;
}
static const char * const *
gdm_session_worker_get_environment (GdmSessionWorker *worker)
{
return (const char * const *) pam_getenvlist (worker->priv->pam_handle);
}
static gboolean
run_script (GdmSessionWorker *worker,
const char *dir)
{
/* scripts are for non-program sessions only */
if (worker->priv->is_program_session) {
return TRUE;
}
return gdm_run_script (dir,
worker->priv->username,
worker->priv->x11_display_name,
worker->priv->display_is_local? NULL : worker->priv->hostname,
worker->priv->x11_authority_file);
}
static void
@@ -2145,61 +2157,61 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
(char **)
environment,
TRUE);
gdm_log_init ();
g_debug ("GdmSessionWorker: child '%s' could not be started: %s",
worker->priv->arguments[0],
g_strerror (errno));
_exit (EXIT_FAILURE);
}
if (worker->priv->session_tty_fd > 0) {
close (worker->priv->session_tty_fd);
worker->priv->session_tty_fd = -1;
}
/* If we end up execing again, make sure we don't use the executable context set up
* by pam_selinux durin pam_open_session
*/
#ifdef HAVE_SELINUX
setexeccon (NULL);
#endif
worker->priv->child_pid = session_pid;
g_debug ("GdmSessionWorker: session opened creating reply...");
g_assert (sizeof (GPid) <= sizeof (int));
g_debug ("GdmSessionWorker: state SESSION_STARTED");
- worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_STARTED;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
gdm_session_worker_watch_child (worker);
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static gboolean
set_up_for_new_vt (GdmSessionWorker *worker)
{
int fd;
char vt_string[256], tty_string[256];
int session_vt = 0;
fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
if (fd < 0) {
g_debug ("GdmSessionWorker: couldn't open VT master: %m");
return FALSE;
}
if (worker->priv->display_is_initial) {
session_vt = atoi (GDM_INITIAL_VT);
} else {
if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
@@ -2368,61 +2380,61 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
break;
case GDM_SESSION_DISPLAY_MODE_NEW_VT:
case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED:
if (!set_up_for_new_vt (worker)) {
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
"Unable to open VT");
return FALSE;
}
break;
}
flags = 0;
if (worker->priv->is_program_session) {
flags |= PAM_SILENT;
}
error_code = pam_open_session (worker->priv->pam_handle, flags);
if (error_code != PAM_SUCCESS) {
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
"%s", pam_strerror (worker->priv->pam_handle, error_code));
goto out;
}
g_debug ("GdmSessionWorker: state SESSION_OPENED");
- worker->priv->state = GDM_SESSION_WORKER_STATE_SESSION_OPENED;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_OPENED);
session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID");
if (session_id != NULL) {
g_free (worker->priv->session_id);
worker->priv->session_id = session_id;
}
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
gdm_session_worker_get_username (worker, NULL);
gdm_session_auditor_report_login (worker->priv->auditor);
return TRUE;
}
static void
gdm_session_worker_set_server_address (GdmSessionWorker *worker,
const char *address)
{
g_free (worker->priv->server_address);
worker->priv->server_address = g_strdup (address);
}
static void
gdm_session_worker_set_is_reauth_session (GdmSessionWorker *worker,
@@ -2445,61 +2457,61 @@ gdm_session_worker_set_property (GObject *object,
case PROP_SERVER_ADDRESS:
gdm_session_worker_set_server_address (self, g_value_get_string (value));
break;
case PROP_IS_REAUTH_SESSION:
gdm_session_worker_set_is_reauth_session (self, g_value_get_boolean (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_session_worker_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdmSessionWorker *self;
self = GDM_SESSION_WORKER (object);
switch (prop_id) {
case PROP_SERVER_ADDRESS:
g_value_set_string (value, self->priv->server_address);
break;
case PROP_IS_REAUTH_SESSION:
g_value_set_boolean (value, self->priv->is_reauth_session);
break;
case PROP_STATE:
- g_value_set_int (value, self->priv->state);
+ g_value_set_enum (value, self->priv->state);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
gdm_session_worker_handle_set_environment_variable (GdmDBusWorker *object,
GDBusMethodInvocation *invocation,
const char *key,
const char *value)
{
GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
gdm_session_worker_set_environment_variable (worker, key, value);
gdm_dbus_worker_complete_set_environment_variable (object, invocation);
return TRUE;
}
static gboolean
gdm_session_worker_handle_set_session_name (GdmDBusWorker *object,
GDBusMethodInvocation *invocation,
const char *session_name)
{
GdmSessionWorker *worker = GDM_SESSION_WORKER (object);
g_debug ("GdmSessionWorker: session name set to %s", session_name);
if (worker->priv->user_settings != NULL)
gdm_session_settings_set_session_name (worker->priv->user_settings,
session_name);
gdm_dbus_worker_complete_set_session_name (object, invocation);
@@ -2646,61 +2658,61 @@ do_authorize (GdmSessionWorker *worker)
g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
}
worker->priv->pending_invocation = NULL;
}
static void
do_accredit (GdmSessionWorker *worker)
{
GError *error;
gboolean res;
/* get kerberos tickets, setup group lists, etc
*/
error = NULL;
res = gdm_session_worker_accredit_user (worker, &error);
if (res) {
gdm_dbus_worker_complete_establish_credentials (GDM_DBUS_WORKER (worker), worker->priv->pending_invocation);
} else {
g_dbus_method_invocation_take_error (worker->priv->pending_invocation, error);
}
worker->priv->pending_invocation = NULL;
}
static void
save_account_details_now (GdmSessionWorker *worker)
{
g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCREDITED);
g_debug ("GdmSessionWorker: saving account details for user %s", worker->priv->username);
- worker->priv->state = GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED;
+ gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
if (worker->priv->user_settings != NULL) {
if (!gdm_session_settings_save (worker->priv->user_settings,
worker->priv->username)) {
g_warning ("could not save session and language settings");
}
}
queue_state_change (worker);
}
static void
on_settings_is_loaded_changed (GdmSessionSettings *user_settings,
GParamSpec *pspec,
GdmSessionWorker *worker)
{
if (!gdm_session_settings_is_loaded (worker->priv->user_settings)) {
return;
}
/* These signal handlers should be disconnected after the loading,
* so that gdm_session_settings_set_* APIs don't cause the emitting
* of Saved*NameRead D-Bus signals any more.
*/
g_signal_handlers_disconnect_by_func (worker->priv->user_settings,
G_CALLBACK (on_saved_session_name_read),
worker);
g_signal_handlers_disconnect_by_func (worker->priv->user_settings,
G_CALLBACK (on_saved_language_name_read),
worker);
@@ -3461,60 +3473,69 @@ worker_interface_init (GdmDBusWorkerIface *interface)
interface->handle_start_reauthentication = gdm_session_worker_handle_start_reauthentication;
}
static void
gdm_session_worker_class_init (GdmSessionWorkerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = gdm_session_worker_get_property;
object_class->set_property = gdm_session_worker_set_property;
object_class->constructor = gdm_session_worker_constructor;
object_class->finalize = gdm_session_worker_finalize;
g_type_class_add_private (klass, sizeof (GdmSessionWorkerPrivate));
g_object_class_install_property (object_class,
PROP_SERVER_ADDRESS,
g_param_spec_string ("server-address",
"server address",
"server address",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_IS_REAUTH_SESSION,
g_param_spec_boolean ("is-reauth-session",
"is reauth session",
"is reauth session",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (object_class,
+ PROP_STATE,
+ g_param_spec_enum ("state",
+ "state",
+ "state",
+ GDM_TYPE_SESSION_WORKER_STATE,
+ GDM_SESSION_WORKER_STATE_NONE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
}
static void
reauthentication_request_free (ReauthenticationRequest *request)
{
g_signal_handlers_disconnect_by_func (request->session,
G_CALLBACK (on_reauthentication_client_connected),
request);
g_signal_handlers_disconnect_by_func (request->session,
G_CALLBACK (on_reauthentication_client_disconnected),
request);
g_signal_handlers_disconnect_by_func (request->session,
G_CALLBACK (on_reauthentication_cancelled),
request);
g_signal_handlers_disconnect_by_func (request->session,
G_CALLBACK (on_reauthentication_conversation_started),
request);
g_signal_handlers_disconnect_by_func (request->session,
G_CALLBACK (on_reauthentication_conversation_stopped),
request);
g_signal_handlers_disconnect_by_func (request->session,
G_CALLBACK (on_reauthentication_verification_complete),
request);
g_clear_object (&request->session);
g_slice_free (ReauthenticationRequest, request);
}
static void
gdm_session_worker_init (GdmSessionWorker *worker)
diff --git a/daemon/session-worker-main.c b/daemon/session-worker-main.c
index 4a3a8ebbe..d96844d2d 100644
--- a/daemon/session-worker-main.c
+++ b/daemon/session-worker-main.c
@@ -37,104 +37,137 @@
#include <glib-object.h>
#include "gdm-common.h"
#include "gdm-log.h"
#include "gdm-session-worker.h"
#include "gdm-settings.h"
#include "gdm-settings-direct.h"
#include "gdm-settings-keys.h"
static GdmSettings *settings = NULL;
static gboolean
on_sigusr1_cb (gpointer user_data)
{
g_debug ("Got USR1 signal");
gdm_log_toggle_debug ();
return TRUE;
}
static gboolean
is_debug_set (void)
{
gboolean debug;
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
return debug;
}
+static gboolean
+on_shutdown_signal_cb (gpointer user_data)
+{
+ GMainLoop *mainloop = user_data;
+
+ g_main_loop_quit (mainloop);
+
+ return FALSE;
+}
+
+static void
+on_state_changed (GdmSessionWorker *worker,
+ GParamSpec *pspec,
+ GMainLoop *main_loop)
+{
+ GdmSessionWorkerState state;
+
+ g_object_get (G_OBJECT (worker), "state", &state, NULL);
+
+ if (state != GDM_SESSION_WORKER_STATE_SESSION_STARTED)
+ return;
+
+ g_unix_signal_add (SIGTERM, on_shutdown_signal_cb, main_loop);
+}
+
static void
on_sigterm_cb (int signal_number)
{
_exit (EXIT_SUCCESS);
}
int
main (int argc,
char **argv)
{
GMainLoop *main_loop;
GOptionContext *context;
GdmSessionWorker *worker;
const char *address;
gboolean is_for_reauth;
static GOptionEntry entries [] = {
{ NULL }
};
signal (SIGTERM, on_sigterm_cb);
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
/* Translators: worker is a helper process that does the work
of starting up a session */
context = g_option_context_new (_("GNOME Display Manager Session Worker"));
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
gdm_log_init ();
settings = gdm_settings_new ();
if (settings == NULL) {
g_warning ("Unable to initialize settings");
exit (EXIT_FAILURE);
}
if (! gdm_settings_direct_init (settings, DATADIR "/gdm/gdm.schemas", "/")) {
g_warning ("Unable to initialize settings");
exit (EXIT_FAILURE);
}
gdm_log_set_debug (is_debug_set ());
address = g_getenv ("GDM_SESSION_DBUS_ADDRESS");
if (address == NULL) {
g_warning ("GDM_SESSION_DBUS_ADDRESS not set");
exit (EXIT_FAILURE);
}
is_for_reauth = g_getenv ("GDM_SESSION_FOR_REAUTH") != NULL;
worker = gdm_session_worker_new (address, is_for_reauth);
main_loop = g_main_loop_new (NULL, FALSE);
+ g_signal_connect (G_OBJECT (worker),
+ "notify::state",
+ G_CALLBACK (on_state_changed),
+ main_loop);
+
g_unix_signal_add (SIGUSR1, on_sigusr1_cb, NULL);
g_main_loop_run (main_loop);
if (worker != NULL) {
+ g_signal_handlers_disconnect_by_func (worker,
+ G_CALLBACK (on_state_changed),
+ main_loop);
g_object_unref (worker);
}
g_main_loop_unref (main_loop);
g_debug ("Worker finished");
return 0;
}
--
2.18.1

View File

@ -1,4 +1,4 @@
From f12d17a6f4f76ba037e9126113684777a070a8f4 Mon Sep 17 00:00:00 2001
From bd5153305b576f29ea3b8835bd2740a5eda2db0f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 20 Aug 2018 14:30:59 -0400
Subject: [PATCH 3/4] daemon: save os-release in accountsservice
@ -8,167 +8,31 @@ when they logged in (to detect upgrades).
This commit saves that information in accountsservice.
---
daemon/Makefile.am | 10 ++
daemon/gdm-session-settings.c | 98 +++++++++++++++++++
data/Makefile.am | 2 +
.../com.redhat.AccountsServiceUser.System.xml | 10 ++
4 files changed, 120 insertions(+)
create mode 100644 data/com.redhat.AccountsServiceUser.System.xml
daemon/gdm-session-settings.c | 98 +++++++++++++++++++
daemon/gdm-session.c | 4 +-
daemon/meson.build | 8 ++
4 files changed, 118 insertions(+), 2 deletions(-)
create mode 100644 daemon/com.redhat.AccountsServiceUser.System.xml
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index 3b1b15122..b77c9276e 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -14,137 +14,147 @@ AM_CPPFLAGS = \
-DLIBEXECDIR=\"$(libexecdir)\" \
-DLOCALSTATEDIR=\"$(localstatedir)\" \
-DLOGDIR=\"$(logdir)\" \
-DSBINDIR=\"$(sbindir)\" \
-DSYSCONFDIR=\"$(sysconfdir)\" \
-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
-DGDM_RUN_DIR=\"$(GDM_RUN_DIR)\" \
-DGDM_XAUTH_DIR=\"$(GDM_XAUTH_DIR)\" \
-DGDM_SCREENSHOT_DIR=\"$(GDM_SCREENSHOT_DIR)\" \
-DGDM_CACHE_DIR=\""$(localstatedir)/cache/gdm"\" \
-DGDM_SESSION_DEFAULT_PATH=\"$(GDM_SESSION_DEFAULT_PATH)\" \
$(DISABLE_DEPRECATED_CFLAGS) \
$(DAEMON_CFLAGS) \
$(XLIB_CFLAGS) \
$(WARN_CFLAGS) \
$(DEBUG_CFLAGS) \
$(SYSTEMD_CFLAGS) \
$(JOURNALD_CFLAGS) \
$(LIBSELINUX_CFLAGS) \
-DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\" \
$(NULL)
BUILT_SOURCES = \
gdm-display-glue.h \
gdm-manager-glue.h \
gdm-local-display-glue.h \
gdm-local-display-factory-glue.h \
gdm-session-glue.h \
gdm-session-worker-glue.h \
gdm-session-enum-types.h \
+ com.redhat.AccountsServiceUser.System.h \
$(NULL)
gdm-session-enum-types.h: gdm-session-enum-types.h.in gdm-session.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
gdm-session-enum-types.c: gdm-session-enum-types.c.in gdm-session.h
$(AM_V_GEN) glib-mkenums --template $^ > $@
gdm-display-glue.c gdm-display-glue.h: gdm-display.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-display-glue \
$(srcdir)/gdm-display.xml
gdm-local-display-glue.c gdm-local-display-glue.h: gdm-local-display.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-local-display-glue \
$(srcdir)/gdm-local-display.xml
gdm-local-display-factory-glue.c gdm-local-display-factory-glue.h : gdm-local-display-factory.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-local-display-factory-glue \
$(srcdir)/gdm-local-display-factory.xml
gdm-manager-glue.c gdm-manager-glue.h : gdm-manager.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-manager-glue \
$(srcdir)/gdm-manager.xml
gdm-session-glue.c gdm-session-glue.h : gdm-session.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-session-glue \
$(srcdir)/gdm-session.xml
gdm-session-worker-glue.c gdm-session-worker-glue.h : gdm-session-worker.xml Makefile.am
$(AM_V_GEN)gdbus-codegen \
--c-namespace=GdmDBus \
--interface-prefix=org.gnome.DisplayManager \
--generate-c-code=gdm-session-worker-glue \
$(srcdir)/gdm-session-worker.xml
+com.redhat.AccountsServiceUser.System.c com.redhat.AccountsServiceUser.System.h: $(top_srcdir)/data/com.redhat.AccountsServiceUser.System.xml Makefile.am
+ $(AM_V_GEN)gdbus-codegen \
+ --c-namespace=Gdm \
+ --interface-prefix=com.redhat \
+ --generate-c-code=com.redhat.AccountsServiceUser.System \
+ $(top_srcdir)/data/com.redhat.AccountsServiceUser.System.xml
diff --git a/daemon/com.redhat.AccountsServiceUser.System.xml b/daemon/com.redhat.AccountsServiceUser.System.xml
new file mode 100644
index 00000000..67f5f302
--- /dev/null
+++ b/daemon/com.redhat.AccountsServiceUser.System.xml
@@ -0,0 +1,10 @@
+<node>
+ <interface name="com.redhat.AccountsServiceUser.System">
+
noinst_PROGRAMS = \
test-session-client \
$(NULL)
test_session_client_SOURCES = \
test-session-client.c \
$(NULL)
nodist_test_session_client_SOURCES = \
gdm-session-glue.h \
gdm-session-glue.c \
gdm-manager-glue.h \
gdm-manager-glue.c \
$(NULL)
test_session_client_LDADD = \
$(DAEMON_LIBS) \
$(NULL)
libexec_PROGRAMS = \
gdm-session-worker \
gdm-wayland-session \
gdm-x-session \
$(NULL)
gdm_session_worker_SOURCES = \
session-worker-main.c \
+ com.redhat.AccountsServiceUser.System.h \
+ com.redhat.AccountsServiceUser.System.c \
gdm-session.c \
gdm-session.h \
gdm-session-settings.h \
gdm-session-settings.c \
gdm-session-auditor.h \
gdm-session-auditor.c \
gdm-session-record.c \
gdm-session-record.h \
gdm-session-worker.h \
gdm-session-worker.c \
gdm-session-worker-job.c \
gdm-session-worker-common.c \
gdm-session-worker-common.h \
gdm-dbus-util.c \
gdm-dbus-util.h \
$(NULL)
if SUPPORTS_PAM_EXTENSIONS
gdm_session_worker_SOURCES += $(top_srcdir)/pam-extensions/gdm-pam-extensions.h
endif
nodist_gdm_session_worker_SOURCES = \
gdm-session-glue.h \
gdm-session-glue.c \
gdm-session-worker-glue.c \
gdm-session-worker-glue.h \
gdm-session-enum-types.c \
gdm-session-enum-types.h \
$(NULL)
+ <annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>
+
+ <property name="id" type="s" access="readwrite"/>
+ <property name="version-id" type="s" access="readwrite"/>
+
+ </interface>
+</node>
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
index 8463fad32..921e4d501 100644
index f2b1addd..a4b7f1a6 100644
--- a/daemon/gdm-session-settings.c
+++ b/daemon/gdm-session-settings.c
@@ -1,70 +1,77 @@
@ -245,15 +109,15 @@ index 8463fad32..921e4d501 100644
PROP_IS_LOADED
};
G_DEFINE_TYPE (GdmSessionSettings, gdm_session_settings, G_TYPE_OBJECT)
G_DEFINE_TYPE_WITH_PRIVATE (GdmSessionSettings,
gdm_session_settings,
G_TYPE_OBJECT)
static void
gdm_session_settings_class_init (GdmSessionSettingsClass *settings_class)
@@ -107,60 +114,62 @@ gdm_session_settings_class_install_properties (GdmSessionSettingsClass *settings
g_object_class_install_property (object_class, PROP_LANGUAGE_NAME, param_spec);
param_spec = g_param_spec_boolean ("is-loaded", NULL, NULL,
FALSE, G_PARAM_READABLE);
FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_property (object_class, PROP_IS_LOADED, param_spec);
}
@ -369,9 +233,9 @@ index 8463fad32..921e4d501 100644
+ }
+ }
+
/* 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);
@ -536,89 +400,212 @@ index 8463fad32..921e4d501 100644
return TRUE;
}
diff --git a/data/Makefile.am b/data/Makefile.am
index 192dfa052..d69021985 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -8,60 +8,62 @@ SUBDIRS = \
$(NULL)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 43da024f..c8e04c1b 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -351,72 +351,72 @@ supports_session_type (GdmSession *self,
if (session_type == NULL)
return TRUE;
initdir = $(gdmconfdir)/Init
postdir = $(gdmconfdir)/PostSession
predir = $(gdmconfdir)/PreSession
postlogindir = $(gdmconfdir)/PostLogin
workingdir = $(GDM_WORKING_DIR)
xauthdir = $(GDM_XAUTH_DIR)
screenshotdir = $(GDM_SCREENSHOT_DIR)
cachedir = $(localstatedir)/cache/gdm
return g_strv_contains ((const char * const *) self->supported_session_types,
session_type);
}
Init: $(srcdir)/Init.in
sed -e 's,[@]X_PATH[@],$(X_PATH),g' \
<$(srcdir)/Init.in >Init
static char **
get_system_session_dirs (GdmSession *self,
const char *type)
{
GArray *search_array = NULL;
char **search_dirs;
int i, j;
const gchar * const *system_data_dirs = g_get_system_data_dirs ();
PreSession: $(srcdir)/PreSession.in
sed -e 's,[@]X_PATH[@],$(X_PATH),g' \
<$(srcdir)/PreSession.in >PreSession
PostSession: $(srcdir)/PostSession.in
sed -e 's,[@]X_PATH[@],$(X_PATH),g' \
<$(srcdir)/PostSession.in >PostSession
static const char *x_search_dirs[] = {
"/etc/X11/sessions/",
DMCONFDIR "/Sessions/",
DATADIR "/gdm/BuiltInSessions/",
DATADIR "/xsessions/",
};
gdm.conf-custom: $(srcdir)/gdm.conf-custom.in
sed -e 's,[@]GDM_DEFAULTS_CONF[@],$(GDM_DEFAULTS_CONF),g' \
<$(srcdir)/gdm.conf-custom.in >gdm.conf-custom
static const char *wayland_search_dir = DATADIR "/wayland-sessions/";
dbusconfdir = $(DBUS_SYS_DIR)
dbusconf_in_files = gdm.conf.in
dbusconf_DATA = $(dbusconf_in_files:.conf.in=.conf)
search_array = g_array_new (TRUE, TRUE, sizeof (char *));
+EXTRA_DIST += com.redhat.AccountsServiceUser.System.xml
for (j = 0; self->supported_session_types[j] != NULL; j++) {
const char *supported_type = self->supported_session_types[j];
- if (g_str_equal (supported_type, "x11") ||
+ if (g_str_equal (supported_type, "x11") &&
(type == NULL || g_str_equal (type, supported_type))) {
for (i = 0; system_data_dirs[i]; i++) {
gchar *dir = g_build_filename (system_data_dirs[i], "xsessions", NULL);
g_array_append_val (search_array, dir);
}
g_array_append_vals (search_array, x_search_dirs, G_N_ELEMENTS (x_search_dirs));
}
#ifdef ENABLE_WAYLAND_SUPPORT
- if (g_str_equal (supported_type, "wayland") ||
+ if (g_str_equal (supported_type, "wayland") &&
(type == NULL || g_str_equal (type, supported_type))) {
for (i = 0; system_data_dirs[i]; i++) {
gchar *dir = g_build_filename (system_data_dirs[i], "wayland-sessions", NULL);
g_array_append_val (search_array, dir);
}
g_array_append_val (search_array, wayland_search_dir);
}
#endif
}
search_dirs = g_strdupv ((char **) search_array->data);
g_array_free (search_array, TRUE);
return search_dirs;
}
static gboolean
is_prog_in_path (const char *prog)
{
char *f;
gboolean ret;
f = g_find_program_in_path (prog);
ret = (f != NULL);
g_free (f);
return ret;
}
diff --git a/daemon/meson.build b/daemon/meson.build
index 2e61b644..71c65039 100644
--- a/daemon/meson.build
+++ b/daemon/meson.build
@@ -15,114 +15,122 @@ local_display_dbus_gen = gnome.gdbus_codegen('gdm-local-display-glue',
'gdm-local-display.xml',
namespace: 'GdmDBus',
interface_prefix: 'org.gnome.DisplayManager',
autocleanup: 'all',
)
local_display_factory_dbus_gen = gnome.gdbus_codegen('gdm-local-display-factory-glue',
'gdm-local-display-factory.xml',
namespace: 'GdmDBus',
interface_prefix: 'org.gnome.DisplayManager',
autocleanup: 'all',
)
manager_dbus_gen = gnome.gdbus_codegen('gdm-manager-glue',
'gdm-manager.xml',
namespace: 'GdmDBus',
interface_prefix: 'org.gnome.DisplayManager',
autocleanup: 'all',
)
session_dbus_gen = gnome.gdbus_codegen('gdm-session-glue',
'gdm-session.xml',
namespace: 'GdmDBus',
interface_prefix: 'org.gnome.DisplayManager',
autocleanup: 'all',
)
session_worker_dbus_gen = gnome.gdbus_codegen('gdm-session-worker-glue',
'gdm-session-worker.xml',
namespace: 'GdmDBus',
interface_prefix: 'org.gnome.DisplayManager',
autocleanup: 'all',
)
+accountsservice_system_user_dbus_gen = gnome.gdbus_codegen('com.redhat.AccountsServiceUser.System',
+ 'com.redhat.AccountsServiceUser.System.xml',
+ namespace: 'Gdm',
+ interface_prefix: 'com.redhat',
+ autocleanup: 'all',
+)
+
@INTLTOOL_SCHEMAS_RULE@
@INTLTOOL_XML_NOMERGE_RULE@
gdm_session_enums = gnome.mkenums('gdm-session-enum-types',
h_template: 'gdm-session-enum-types.h.in',
c_template: 'gdm-session-enum-types.c.in',
sources: 'gdm-session.h',
)
gdm_session_worker_enums = gnome.mkenums('gdm-session-worker-enum-types',
h_template: 'gdm-session-worker-enum-types.h.in',
c_template: 'gdm-session-worker-enum-types.c.in',
sources: 'gdm-session-worker.h',
)
# dconf database and profile
dconf_db_files = \
dconf/defaults/00-upstream-settings \
dconf/defaults/locks/00-upstream-settings-locks
# Daemons deps
gdm_daemon_deps = [
libgdmcommon_dep,
accountsservice_dep,
gobject_dep,
gio_dep,
gio_unix_dep,
libpam_dep,
x_deps,
xcb_dep,
]
dconfdbdir = $(pkgdatadir)
dconfdb_DATA = greeter-dconf-defaults
greeter-dconf-defaults: $(dconf_db_files)
$(AM_V_GEN) dconf compile $@ $(srcdir)/dconf/defaults
if xdmcp_dep.found() and get_option('tcp-wrappers')
gdm_daemon_deps += libwrap_dep
endif
dconfprofiledir = $(DATADIR)/dconf/profile
dconfprofile_DATA = dconf/gdm
# test-session-client
test_session_client_src = [
'test-session-client.c',
session_dbus_gen,
manager_dbus_gen,
]
gsettings_SCHEMAS = org.gnome.login-screen.gschema.xml
@GSETTINGS_RULES@
test_session_client = executable('test-session-client',
test_session_client_src,
dependencies: gdm_daemon_deps,
include_directories: config_h_dir,
)
schemasdir = $(pkgdatadir)
schemas_in_files = gdm.schemas.in
schemas_DATA = $(schemas_in_files:.schemas.in=.schemas)
# Session worker
gdm_session_worker_src = [
'session-worker-main.c',
'gdm-session.c',
'gdm-session-settings.c',
'gdm-session-auditor.c',
'gdm-session-record.c',
'gdm-session-worker.c',
'gdm-session-worker-job.c',
'gdm-session-worker-common.c',
'gdm-dbus-util.c',
dbus_gen,
session_dbus_gen,
session_worker_dbus_gen,
+ accountsservice_system_user_dbus_gen,
gdm_session_enums,
gdm_session_worker_enums,
]
gdm.schemas.in: $(srcdir)/gdm.schemas.in.in
sed -e 's,[@]GDMPREFETCHCMD[@],$(GDMPREFETCHCMD),g' \
-e 's,[@]GDM_CUSTOM_CONF[@],$(GDM_CUSTOM_CONF),g' \
-e 's,[@]GDM_USER_PATH[@],$(GDM_USER_PATH),g' \
-e 's,[@]GDM_USERNAME[@],$(GDM_USERNAME),g' \
-e 's,[@]GDM_GROUPNAME[@],$(GDM_GROUPNAME),g' \
-e 's,[@]HALT_COMMAND[@],$(HALT_COMMAND),g' \
diff --git a/data/com.redhat.AccountsServiceUser.System.xml b/data/com.redhat.AccountsServiceUser.System.xml
new file mode 100644
index 000000000..67f5f302c
--- /dev/null
+++ b/data/com.redhat.AccountsServiceUser.System.xml
@@ -0,0 +1,10 @@
+<node>
+ <interface name="com.redhat.AccountsServiceUser.System">
+
+ <annotation name="org.freedesktop.Accounts.VendorExtension" value="true"/>
+
+ <property name="id" type="s" access="readwrite"/>
+ <property name="version-id" type="s" access="readwrite"/>
+
+ </interface>
+</node>
gdm_session_worker_deps = [
gdm_daemon_deps,
]
gdm_session_worker_includes = [
config_h_dir,
]
if pam_extensions_supported
gdm_session_worker_src += '../pam-extensions/gdm-pam-extensions.h'
gdm_session_worker_includes += pam_extensions_inc
endif
if libaudit_dep.found()
gdm_session_worker_deps += libaudit_dep
gdm_session_worker_src += [
'gdm-session-linux-auditor.c',
]
endif
if have_adt
gdm_session_worker_src += 'gdm-session-solaris-auditor.c'
endif
gdm_session_worker = executable('gdm-session-worker',
--
2.17.1
2.27.0

View File

@ -1,83 +0,0 @@
From db47f4de3aab9f4cd6b381ecd9341c94add59bf9 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Wed, 16 May 2018 18:36:50 +0100
Subject: [PATCH 03/51] local-display-factory: Use correct session-type for new
transient displays
Use the new gdm_local_display_factory_use_wayland() helper to correctly
set the session-type properties for displays created through
gdm_local_display_factory_create_transient_display().
---
daemon/gdm-local-display-factory.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index b21e3aee0..e52360a56 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -194,60 +194,62 @@ gdm_local_display_factory_use_wayland (void)
if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
return TRUE;
}
#endif
return FALSE;
}
/*
Example:
dbus-send --system --dest=org.gnome.DisplayManager \
--type=method_call --print-reply --reply-timeout=2000 \
/org/gnome/DisplayManager/Manager \
org.gnome.DisplayManager.Manager.GetDisplays
*/
gboolean
gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
char **id,
GError **error)
{
gboolean ret;
GdmDisplay *display = NULL;
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
ret = FALSE;
g_debug ("GdmLocalDisplayFactory: Creating transient display");
#ifdef ENABLE_USER_DISPLAY_SERVER
display = gdm_local_display_new ();
+ if (gdm_local_display_factory_use_wayland ())
+ g_object_set (G_OBJECT (display), "session-type", "wayland", NULL);
#else
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
#endif
g_object_set (display,
"seat-id", "seat0",
"allow-timed-login", FALSE,
NULL);
store_display (factory, display);
if (! gdm_display_manage (display)) {
display = NULL;
goto out;
}
if (! gdm_display_get_id (display, id, NULL)) {
display = NULL;
goto out;
}
ret = TRUE;
out:
/* ref either held by store or not at all */
--
2.27.0

View File

@ -1,227 +0,0 @@
From 7b83c1dc9645cabadfeb253d7eca427f6a26d10f Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
Date: Thu, 31 Jan 2019 17:51:52 +0000
Subject: [PATCH 3/4] session: Don't allow greeter operations on an running
session
If a client has a reference to a session that starts running,
refuse to allow further operations on the session.
CVE-2019-3825
---
daemon/gdm-session.c | 75 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 75 insertions(+)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index f23a83c5e..a8263ba11 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -1401,130 +1401,205 @@ gdm_session_handle_client_begin_verification_for_user (GdmDBusUserVerifier *u
static gboolean
gdm_session_handle_client_answer_query (GdmDBusUserVerifier *user_verifier_interface,
GDBusMethodInvocation *invocation,
const char *service_name,
const char *answer,
GdmSession *self)
{
gdm_dbus_user_verifier_complete_answer_query (user_verifier_interface,
invocation);
gdm_session_answer_query (self, service_name, answer);
return TRUE;
}
static gboolean
gdm_session_handle_client_cancel (GdmDBusUserVerifier *user_verifier_interface,
GDBusMethodInvocation *invocation,
GdmSession *self)
{
gdm_dbus_user_verifier_complete_cancel (user_verifier_interface,
invocation);
gdm_session_cancel (self);
return TRUE;
}
static gboolean
gdm_session_handle_client_select_session (GdmDBusGreeter *greeter_interface,
GDBusMethodInvocation *invocation,
const char *session,
GdmSession *self)
{
+ if (gdm_session_is_running (self)) {
+ const char *username;
+
+ username = gdm_session_get_username (self);
+ g_debug ("GdmSession: refusing to select session %s since it's already running (for user %s)",
+ session,
+ username);
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Session already running for user %s",
+ username);
+ return TRUE;
+ }
+
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_complete_select_session (greeter_interface,
invocation);
}
gdm_session_select_session (self, session);
return TRUE;
}
static gboolean
gdm_session_handle_client_select_user (GdmDBusGreeter *greeter_interface,
GDBusMethodInvocation *invocation,
const char *username,
GdmSession *self)
{
+ if (gdm_session_is_running (self)) {
+ const char *session_username;
+
+ session_username = gdm_session_get_username (self);
+ g_debug ("GdmSession: refusing to select user %s, since session (%p) already running (for user %s)",
+ username,
+ self,
+ session_username);
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Session already running for user %s",
+ session_username);
+ return TRUE;
+ }
+
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_complete_select_user (greeter_interface,
invocation);
}
g_debug ("GdmSession: client selected user '%s' on session (%p)", username, self);
gdm_session_select_user (self, username);
return TRUE;
}
static gboolean
gdm_session_handle_client_start_session_when_ready (GdmDBusGreeter *greeter_interface,
GDBusMethodInvocation *invocation,
const char *service_name,
gboolean client_is_ready,
GdmSession *self)
{
+ if (gdm_session_is_running (self)) {
+ const char *username;
+
+ username = gdm_session_get_username (self);
+ g_debug ("GdmSession: refusing to start session (%p), since it's already running (for user %s)",
+ self,
+ username);
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Session already running for user %s",
+ username);
+ return TRUE;
+ }
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_complete_start_session_when_ready (greeter_interface,
invocation);
}
g_signal_emit (G_OBJECT (self),
signals [CLIENT_READY_FOR_SESSION_TO_START],
0,
service_name,
client_is_ready);
return TRUE;
}
static gboolean
gdm_session_handle_get_timed_login_details (GdmDBusGreeter *greeter_interface,
GDBusMethodInvocation *invocation,
GdmSession *self)
{
+ if (gdm_session_is_running (self)) {
+ const char *username;
+
+ username = gdm_session_get_username (self);
+ g_debug ("GdmSession: refusing to give timed login details, session (%p) already running (for user %s)",
+ self,
+ username);
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Session already running for user %s",
+ username);
+ return TRUE;
+ }
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_complete_get_timed_login_details (greeter_interface,
invocation,
self->priv->timed_login_username != NULL,
self->priv->timed_login_username != NULL? self->priv->timed_login_username : "",
self->priv->timed_login_delay);
if (self->priv->timed_login_username != NULL) {
gdm_dbus_greeter_emit_timed_login_requested (self->priv->greeter_interface,
self->priv->timed_login_username,
self->priv->timed_login_delay);
}
}
return TRUE;
}
static gboolean
gdm_session_handle_client_begin_auto_login (GdmDBusGreeter *greeter_interface,
GDBusMethodInvocation *invocation,
const char *username,
GdmSession *self)
{
+ const char *session_username;
+
+ if (gdm_session_is_running (self)) {
+ session_username = gdm_session_get_username (self);
+ g_debug ("GdmSession: refusing auto login operation, session (%p) already running for user %s (%s requested)",
+ self,
+ session_username,
+ username);
+ g_dbus_method_invocation_return_error (invocation,
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_INVALID_ARGS,
+ "Session already owned by user %s",
+ session_username);
+ return TRUE;
+ }
+
if (self->priv->greeter_interface != NULL) {
gdm_dbus_greeter_complete_begin_auto_login (greeter_interface,
invocation);
}
g_debug ("GdmSession: client requesting automatic login for user '%s' on session '%s' (%p)",
username,
gdm_session_get_session_id (self),
self);
gdm_session_setup_for_user (self, "gdm-autologin", username);
return TRUE;
}
static void
export_user_verifier_interface (GdmSession *self,
GDBusConnection *connection)
{
GdmDBusUserVerifier *user_verifier_interface;
user_verifier_interface = GDM_DBUS_USER_VERIFIER (gdm_dbus_user_verifier_skeleton_new ());
g_object_set_data (G_OBJECT (connection), "gdm-session", self);
g_signal_connect (user_verifier_interface,
"handle-enable-extensions",
G_CALLBACK (gdm_session_handle_client_enable_extensions),
connection);
g_signal_connect (user_verifier_interface,
"handle-begin-verification",
--
2.21.0

View File

@ -1,7 +1,7 @@
From b8c942b5f191eaa39ac1e578fa019b32a516cd5c Mon Sep 17 00:00:00 2001
From 64e8db8432158e5115df18a03bb87ecc1d58ae63 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 11 Feb 2019 10:32:55 -0500
Subject: [PATCH] session: ensure login screen over XDMCP connects to its
Subject: [PATCH 3/3] session: ensure login screen over XDMCP connects to its
session
Right now GTK preferentially picks the wayland display over an
@ -17,10 +17,10 @@ the session is X11.
1 file changed, 19 insertions(+)
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index e6640aac7..0f821e390 100644
index 77d6b8ff0..357e4a297 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2614,60 +2614,79 @@ set_up_session_environment (GdmSession *self)
@@ -2697,60 +2697,79 @@ set_up_session_environment (GdmSession *self)
}
static void
@ -42,8 +42,8 @@ index e6640aac7..0f821e390 100644
{
const char *session_type = "x11";
if (self->priv->session_type != NULL) {
session_type = self->priv->session_type;
if (self->session_type != NULL) {
session_type = self->session_type;
}
gdm_dbus_worker_call_set_environment_variable (conversation->worker_proxy,
@ -101,5 +101,5 @@ index e6640aac7..0f821e390 100644
gpointer key, value;
--
2.18.1
2.30.1

View File

@ -1,85 +0,0 @@
From 1987a539495f38ade3efc561f65b56316080356e Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 24 Jun 2019 16:21:59 -0400
Subject: [PATCH 3/3] session-worker: uninitialize pam if worker is killed
Right nowe don't uninitialize pam or switch back to the
starting VT if the worker is killed before the session.
This commit fixes that.
---
daemon/gdm-session-worker.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index aa288ac8e..0322037e0 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -3552,60 +3552,64 @@ gdm_session_worker_init (GdmSessionWorker *worker)
static void
gdm_session_worker_unwatch_child (GdmSessionWorker *worker)
{
if (worker->priv->child_watch_id == 0)
return;
g_source_remove (worker->priv->child_watch_id);
worker->priv->child_watch_id = 0;
}
static void
gdm_session_worker_finalize (GObject *object)
{
GdmSessionWorker *worker;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_SESSION_WORKER (object));
worker = GDM_SESSION_WORKER (object);
g_return_if_fail (worker->priv != NULL);
gdm_session_worker_unwatch_child (worker);
if (worker->priv->child_pid > 0) {
gdm_signal_pid (worker->priv->child_pid, SIGTERM);
gdm_wait_on_pid (worker->priv->child_pid);
}
+ if (worker->priv->pam_handle != NULL) {
+ gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
+ }
+
g_clear_object (&worker->priv->user_settings);
g_free (worker->priv->service);
g_free (worker->priv->x11_display_name);
g_free (worker->priv->x11_authority_file);
g_free (worker->priv->display_device);
g_free (worker->priv->display_seat_id);
g_free (worker->priv->hostname);
g_free (worker->priv->username);
g_free (worker->priv->server_address);
g_strfreev (worker->priv->arguments);
g_strfreev (worker->priv->extensions);
g_hash_table_unref (worker->priv->reauthentication_requests);
G_OBJECT_CLASS (gdm_session_worker_parent_class)->finalize (object);
}
GdmSessionWorker *
gdm_session_worker_new (const char *address,
gboolean is_reauth_session)
{
GObject *object;
object = g_object_new (GDM_TYPE_SESSION_WORKER,
"server-address", address,
"is-reauth-session", is_reauth_session,
NULL);
return GDM_SESSION_WORKER (object);
}
--
2.18.1

View File

@ -1,87 +0,0 @@
From 7c9e236f9015aae2ea5868b67ff8036766cb7099 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 15 Sep 2020 11:28:48 -0400
Subject: [PATCH 3/3] xdmcp-display-factory: Clear launch environment when done
with it
The XDMCP disply factory examines the sessions of its displays'
launch environments when the displays change status.
Unfortunately it leaks a reference to the launch environment when
doing that.
This commit fixes the reference leak which leads to an fd leak.
---
daemon/gdm-xdmcp-display-factory.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
index 2e14beab4..98232113f 100644
--- a/daemon/gdm-xdmcp-display-factory.c
+++ b/daemon/gdm-xdmcp-display-factory.c
@@ -2091,60 +2091,62 @@ on_display_status_changed (GdmDisplay *display,
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
break;
case GDM_DISPLAY_FAILED:
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
break;
case GDM_DISPLAY_UNMANAGED:
if (session != NULL) {
g_signal_handlers_disconnect_by_func (G_OBJECT (session),
G_CALLBACK (on_client_disconnected),
display);
}
break;
case GDM_DISPLAY_PREPARED:
break;
case GDM_DISPLAY_MANAGED:
if (session != NULL) {
g_signal_connect_object (G_OBJECT (session),
"client-disconnected",
G_CALLBACK (on_client_disconnected),
display, G_CONNECT_SWAPPED);
g_signal_connect_object (G_OBJECT (session),
"disconnected",
G_CALLBACK (on_client_disconnected),
display, G_CONNECT_SWAPPED);
}
break;
default:
g_assert_not_reached ();
break;
}
+
+ g_clear_object (&launch_environment);
}
static GdmDisplay *
gdm_xdmcp_display_create (GdmXdmcpDisplayFactory *factory,
const char *hostname,
GdmAddress *address,
int displaynum)
{
GdmDisplay *display;
GdmDisplayStore *store;
gboolean use_chooser;
g_debug ("GdmXdmcpDisplayFactory: Creating xdmcp display for %s:%d",
hostname ? hostname : "(null)", displaynum);
use_chooser = FALSE;
if (factory->priv->honor_indirect) {
IndirectClient *ic;
ic = indirect_client_lookup (factory, address);
/* This was an indirect thingie and nothing was yet chosen,
* use a chooser */
if (ic != NULL && ic->chosen_address == NULL) {
use_chooser = TRUE;
}
}
if (use_chooser) {
display = gdm_xdmcp_chooser_display_new (hostname,
--
2.26.2

View File

@ -0,0 +1,122 @@
From e3a7ca44c0153ffa895786eabb020810b138eea2 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 14 Sep 2021 11:00:33 -0400
Subject: [PATCH 3/3] 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 ce8f026e1..558458f1c 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.31.1

View File

@ -1,105 +0,0 @@
From 15a19ac7856c539aa9cfbf76997d18b0275aae35 Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
Date: Mon, 4 Feb 2019 15:12:38 +0000
Subject: [PATCH 4/4] GdmManager: Don't perform timed login if session gets
started
At the moment it's possible for the login screen to initiate
a timed login operation shortly after a user successfully starts
their session.
GDM won't complete the timed login operation, since a session is
already running, but will erroneously overwrite the username
associated with the session, misattributing the users session
to the timed login user.
Later, attempts to log in as the timed user will instead unlock the
session for the other user, since that session is now associated
with the timed login user.
This commit refuses timed login requests on sessions that are
already running, so the username doesn't get corrupted.
CVE-2019-3825
Closes https://gitlab.gnome.org/GNOME/gdm/issues/460
---
daemon/gdm-manager.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 0cc06a978..056560b20 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -2116,60 +2116,68 @@ on_session_client_ready_for_session_to_start (GdmSession *session,
} else {
g_debug ("GdmManager: Will start session when ready and told");
}
waiting_to_start_user_session = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session),
"waiting-to-start"));
g_object_set_data (G_OBJECT (session),
"start-when-ready",
GINT_TO_POINTER (client_is_ready));
if (client_is_ready && waiting_to_start_user_session) {
start_user_session_if_ready (manager, session, service_name);
}
}
static void
on_session_client_connected (GdmSession *session,
GCredentials *credentials,
GPid pid_of_client,
GdmManager *manager)
{
GdmDisplay *display;
char *username;
int delay;
gboolean enabled;
gboolean allow_timed_login = FALSE;
g_debug ("GdmManager: client with pid %d connected", (int) pid_of_client);
+ if (gdm_session_is_running (session)) {
+ const char *session_username;
+ session_username = gdm_session_get_username (session);
+ g_debug ("GdmManager: ignoring connection, since session already running (for user %s)",
+ session_username);
+ return;
+ }
+
display = get_display_for_user_session (session);
if (display == NULL) {
return;
}
if (!display_is_on_seat0 (display)) {
return;
}
#ifdef WITH_PLYMOUTH
if (manager->priv->plymouth_is_running) {
plymouth_quit_with_transition ();
manager->priv->plymouth_is_running = FALSE;
}
#endif
g_object_get (G_OBJECT (display), "allow-timed-login", &allow_timed_login, NULL);
if (!allow_timed_login) {
return;
}
enabled = get_timed_login_details (manager, &username, &delay);
if (! enabled) {
return;
}
gdm_session_set_timed_login_details (session, username, delay);
--
2.21.0

View File

@ -1,4 +1,4 @@
From c673a7dd781da5ae0d64e13eb83c17e130231931 Mon Sep 17 00:00:00 2001
From b7c0541ffccf43994a3e418c4012b17a6dd8b630 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 20 Aug 2018 14:30:59 -0400
Subject: [PATCH 4/4] daemon: handle upgrades from RHEL 7
@ -12,10 +12,11 @@ or not they were using RHEL 7 and in the event they were
try to get the right settings.
---
daemon/gdm-session-settings.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
daemon/gdm-session.c | 19 ++++++++-----------
2 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/daemon/gdm-session-settings.c b/daemon/gdm-session-settings.c
index 921e4d501..0ce2e7de2 100644
index a4b7f1a6..a84b2ffa 100644
--- a/daemon/gdm-session-settings.c
+++ b/daemon/gdm-session-settings.c
@@ -270,95 +270,114 @@ gdm_session_settings_get_property (GObject *object,
@ -79,9 +80,9 @@ index 921e4d501..0ce2e7de2 100644
}
}
/* 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);
@ -133,6 +134,117 @@ index 921e4d501..0ce2e7de2 100644
G_CALLBACK (on_user_is_loaded_changed),
settings);
}
--
2.17.1
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index c8e04c1b..3103e9df 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -3205,98 +3205,95 @@ gdm_session_get_session_id (GdmSession *self)
return conversation->session_id;
}
const char *
gdm_session_get_conversation_session_id (GdmSession *self,
const char *service_name)
{
GdmSessionConversation *conversation;
g_return_val_if_fail (GDM_IS_SESSION (self), NULL);
conversation = find_conversation_by_name (self, service_name);
if (conversation == NULL) {
return NULL;
}
return conversation->session_id;
}
static char *
get_session_filename (GdmSession *self)
{
return g_strdup_printf ("%s.desktop", get_session_name (self));
}
#ifdef ENABLE_WAYLAND_SUPPORT
static gboolean
gdm_session_is_wayland_session (GdmSession *self)
{
- GKeyFile *key_file;
+ g_autoptr (GKeyFile) key_file = NULL;
gboolean is_wayland_session = FALSE;
- char *filename;
- char *full_path = NULL;
+ g_autofree char *filename = NULL;
+ g_autofree char *full_path = NULL;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
filename = get_session_filename (self);
if (supports_session_type (self, "wayland")) {
key_file = load_key_file_for_file (self, filename, NULL, &full_path);
if (key_file == NULL) {
goto out;
}
- }
- if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
- is_wayland_session = TRUE;
+ if (full_path != NULL && strstr (full_path, "/wayland-sessions/") != NULL) {
+ is_wayland_session = TRUE;
+ }
}
- g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
out:
- g_clear_pointer (&key_file, g_key_file_free);
- g_free (filename);
+ g_debug ("GdmSession: checking if file '%s' is wayland session: %s", filename, is_wayland_session? "yes" : "no");
return is_wayland_session;
}
#endif
static void
update_session_type (GdmSession *self)
{
#ifdef ENABLE_WAYLAND_SUPPORT
gboolean is_wayland_session = FALSE;
- if (supports_session_type (self, "wayland"))
- is_wayland_session = gdm_session_is_wayland_session (self);
+ is_wayland_session = gdm_session_is_wayland_session (self);
if (is_wayland_session) {
set_session_type (self, "wayland");
} else {
set_session_type (self, NULL);
}
#endif
}
gboolean
gdm_session_session_registers (GdmSession *self)
{
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) key_file = NULL;
gboolean session_registers = FALSE;
g_autofree char *filename = NULL;
g_return_val_if_fail (self != NULL, FALSE);
g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
filename = get_session_filename (self);
key_file = load_key_file_for_file (self, filename, NULL, NULL);
session_registers = g_key_file_get_boolean (key_file,
G_KEY_FILE_DESKTOP_GROUP,
"X-GDM-SessionRegisters",
&error);
if (!session_registers &&
error != NULL &&
--
2.27.0

View File

@ -1,28 +0,0 @@
From f32adbe9bf26d502cb055b3a6cb98fc57e06bf13 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 26 Jul 2019 14:06:16 -0400
Subject: [PATCH 4/4] 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 72201c1fd..202ab6753 100644
--- a/data/gdm.service.in
+++ b/data/gdm.service.in
@@ -21,6 +21,7 @@ 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
--
2.18.1

View File

@ -1,137 +0,0 @@
From e2e5d2a7d73baa7c24d1f14b276cb653c06dd82f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 1 Aug 2018 15:46:11 -0400
Subject: [PATCH 04/51] manager: make get_login_window_session_id fail if no
login screen
Right now we oddly succeed from get_login_window_session_id
if we can't find a login window.
None of the caller expect that, so fail instead.
---
daemon/gdm-manager.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index e44b94373..a9d5628ea 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1372,113 +1372,113 @@ maybe_start_pending_initial_login (GdmManager *manager,
NULL);
if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) {
start_user_session (manager, operation);
manager->priv->initial_login_operation = NULL;
}
g_free (greeter_seat_id);
g_free (user_session_seat_id);
}
static gboolean
get_login_window_session_id (const char *seat_id,
char **session_id)
{
gboolean ret;
int res, i;
char **sessions;
char *service_id;
char *service_class;
char *state;
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
if (res < 0) {
g_debug ("Failed to determine sessions: %s", strerror (-res));
return FALSE;
}
if (sessions == NULL || sessions[0] == NULL) {
*session_id = NULL;
- ret = TRUE;
+ ret = FALSE;
goto out;
}
for (i = 0; sessions[i]; i ++) {
res = sd_session_get_class (sessions[i], &service_class);
if (res < 0) {
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_class, "greeter") != 0) {
free (service_class);
continue;
}
free (service_class);
ret = sd_session_get_state (sessions[i], &state);
if (ret < 0) {
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (g_strcmp0 (state, "closing") == 0) {
free (state);
continue;
}
free (state);
res = sd_session_get_service (sessions[i], &service_id);
if (res < 0) {
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_id, "gdm-launch-environment") == 0) {
*session_id = g_strdup (sessions[i]);
ret = TRUE;
free (service_id);
goto out;
}
free (service_id);
}
*session_id = NULL;
- ret = TRUE;
+ ret = FALSE;
out:
if (sessions) {
for (i = 0; sessions[i]; i ++) {
free (sessions[i]);
}
free (sessions);
}
return ret;
}
static void
activate_login_window_session_on_seat (GdmManager *self,
const char *seat_id)
{
char *session_id;
if (!get_login_window_session_id (seat_id, &session_id)) {
return;
}
activate_session_id (self, seat_id, session_id);
}
static void
maybe_activate_other_session (GdmManager *self,
GdmDisplay *old_display)
{
--
2.27.0

View File

@ -1,79 +0,0 @@
From 34238a9e845455ae2b92159c71b75b7abedc2eb9 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Mon, 18 Jun 2018 12:33:42 +0200
Subject: [PATCH 05/51] manager: avoid leaking session_id
get_login_window_session_id() duplicates the session id.
---
daemon/gdm-manager.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index a9d5628ea..71f55ec65 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1449,60 +1449,61 @@ get_login_window_session_id (const char *seat_id,
free (service_id);
}
*session_id = NULL;
ret = FALSE;
out:
if (sessions) {
for (i = 0; sessions[i]; i ++) {
free (sessions[i]);
}
free (sessions);
}
return ret;
}
static void
activate_login_window_session_on_seat (GdmManager *self,
const char *seat_id)
{
char *session_id;
if (!get_login_window_session_id (seat_id, &session_id)) {
return;
}
activate_session_id (self, seat_id, session_id);
+ g_free (session_id);
}
static void
maybe_activate_other_session (GdmManager *self,
GdmDisplay *old_display)
{
char *seat_id = NULL;
char *session_id;
int ret;
g_object_get (G_OBJECT (old_display),
"seat-id", &seat_id,
NULL);
ret = sd_seat_get_active (seat_id, &session_id, NULL);
if (ret == 0) {
GdmDisplay *display;
display = gdm_display_store_find (self->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
if (display == NULL) {
activate_login_window_session_on_seat (self, seat_id);
}
}
g_free (seat_id);
}
--
2.27.0

View File

@ -1,89 +0,0 @@
From 454a3daad5148a8ef30cb298af82aa0713e73af7 Mon Sep 17 00:00:00 2001
From: Lubomir Rintel <lkundrak@v3.sk>
Date: Mon, 18 Jun 2018 12:33:51 +0200
Subject: [PATCH 06/51] manager: gracefully handle the case of no session for
login window
get_login_window_session_id() will return TRUE with session_id=NULL when
there's no session. This restults in an assertion failure on
constructing the o.fd.login1.Manager.ActivateSessionOnSeat() arguments:
GLib: g_variant_new_string: assertion 'string != NULL' failed
---
daemon/gdm-manager.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 71f55ec65..7a5554e9d 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1448,62 +1448,64 @@ get_login_window_session_id (const char *seat_id,
}
free (service_id);
}
*session_id = NULL;
ret = FALSE;
out:
if (sessions) {
for (i = 0; sessions[i]; i ++) {
free (sessions[i]);
}
free (sessions);
}
return ret;
}
static void
activate_login_window_session_on_seat (GdmManager *self,
const char *seat_id)
{
char *session_id;
if (!get_login_window_session_id (seat_id, &session_id)) {
return;
}
- activate_session_id (self, seat_id, session_id);
- g_free (session_id);
+ if (session_id) {
+ activate_session_id (self, seat_id, session_id);
+ g_free (session_id);
+ }
}
static void
maybe_activate_other_session (GdmManager *self,
GdmDisplay *old_display)
{
char *seat_id = NULL;
char *session_id;
int ret;
g_object_get (G_OBJECT (old_display),
"seat-id", &seat_id,
NULL);
ret = sd_seat_get_active (seat_id, &session_id, NULL);
if (ret == 0) {
GdmDisplay *display;
display = gdm_display_store_find (self->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
if (display == NULL) {
activate_login_window_session_on_seat (self, seat_id);
}
}
g_free (seat_id);
}
--
2.27.0

View File

@ -1,432 +0,0 @@
From 2fc9a5f9db7c9d2ab828bcff4ee5dec9c3cf3d3c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 1 Aug 2018 16:34:30 -0400
Subject: [PATCH 07/51] common: dedupe gdm_get_login_window_session_id
Right now there are two slightly different cut-and-pastes of
the function to get the session id of the login session in
the code.
This commit deduplicates them.
---
common/gdm-common.c | 47 ++++++++++++++++++++++++++++++++------------
common/gdm-common.h | 2 ++
daemon/gdm-manager.c | 4 ++--
3 files changed, 38 insertions(+), 15 deletions(-)
diff --git a/common/gdm-common.c b/common/gdm-common.c
index c44fa998d..00daf0df8 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -364,186 +364,207 @@ create_transient_display (GDBusConnection *connection,
static gboolean
activate_session_id (GDBusConnection *connection,
const char *seat_id,
const char *session_id)
{
GError *local_error = NULL;
GVariant *reply;
reply = g_dbus_connection_call_sync (connection,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ActivateSessionOnSeat",
g_variant_new ("(ss)", session_id, seat_id),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, &local_error);
if (reply == NULL) {
g_warning ("Unable to activate session: %s", local_error->message);
g_error_free (local_error);
return FALSE;
}
g_variant_unref (reply);
return TRUE;
}
-static gboolean
-get_login_window_session_id (const char *seat_id,
- char **session_id)
+gboolean
+gdm_get_login_window_session_id (const char *seat_id,
+ char **session_id)
{
gboolean ret;
int res, i;
char **sessions;
+ char *service_id;
char *service_class;
char *state;
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
if (res < 0) {
g_debug ("Failed to determine sessions: %s", strerror (-res));
return FALSE;
}
if (sessions == NULL || sessions[0] == NULL) {
*session_id = NULL;
- ret = TRUE;
+ ret = FALSE;
goto out;
}
for (i = 0; sessions[i]; i ++) {
+
res = sd_session_get_class (sessions[i], &service_class);
if (res < 0) {
+ if (res == -ENOENT) {
+ free (service_class);
+ continue;
+ }
+
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_class, "greeter") != 0) {
free (service_class);
continue;
}
free (service_class);
ret = sd_session_get_state (sessions[i], &state);
if (ret < 0) {
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (g_strcmp0 (state, "closing") == 0) {
free (state);
continue;
}
free (state);
- *session_id = g_strdup (sessions[i]);
- ret = TRUE;
- break;
+ res = sd_session_get_service (sessions[i], &service_id);
+ if (res < 0) {
+ g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
+ ret = FALSE;
+ goto out;
+ }
+ if (strcmp (service_id, "gdm-launch-environment") == 0) {
+ *session_id = g_strdup (sessions[i]);
+ ret = TRUE;
+
+ free (service_id);
+ goto out;
+ }
+
+ free (service_id);
}
*session_id = NULL;
- ret = TRUE;
+ ret = FALSE;
out:
- for (i = 0; sessions[i]; i ++) {
- free (sessions[i]);
- }
+ if (sessions) {
+ for (i = 0; sessions[i]; i ++) {
+ free (sessions[i]);
+ }
- free (sessions);
+ free (sessions);
+ }
return ret;
}
static gboolean
goto_login_session (GDBusConnection *connection,
GError **error)
{
gboolean ret;
int res;
char *our_session;
char *session_id;
char *seat_id;
ret = FALSE;
session_id = NULL;
seat_id = NULL;
/* First look for any existing LoginWindow sessions on the seat.
If none are found, create a new one. */
/* Note that we mostly use free () here, instead of g_free ()
* since the data allocated is from libsystemd-logind, which
* does not use GLib's g_malloc (). */
res = sd_pid_get_session (0, &our_session);
if (res < 0) {
g_debug ("failed to determine own session: %s", strerror (-res));
g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current session."));
return FALSE;
}
res = sd_session_get_seat (our_session, &seat_id);
free (our_session);
if (res < 0) {
g_debug ("failed to determine own seat: %s", strerror (-res));
g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current seat."));
return FALSE;
}
res = sd_seat_can_multi_session (seat_id);
if (res < 0) {
free (seat_id);
g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to determine whether to switch to an existing login screen or start up a new login screen."));
return FALSE;
}
if (res == 0) {
free (seat_id);
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to start up a new login screen."));
return FALSE;
}
- res = get_login_window_session_id (seat_id, &session_id);
+ res = gdm_get_login_window_session_id (seat_id, &session_id);
if (res && session_id != NULL) {
res = activate_session_id (connection, seat_id, session_id);
if (res) {
ret = TRUE;
}
}
if (! ret && g_strcmp0 (seat_id, "seat0") == 0) {
res = create_transient_display (connection, error);
if (res) {
ret = TRUE;
}
}
free (seat_id);
g_free (session_id);
return ret;
}
gboolean
gdm_goto_login_session (GError **error)
{
GError *local_error;
GDBusConnection *connection;
local_error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local_error);
if (connection == NULL) {
diff --git a/common/gdm-common.h b/common/gdm-common.h
index 8d83a1246..c9cbd9c48 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -26,51 +26,53 @@
#include <errno.h>
#define VE_IGNORE_EINTR(expr) \
do { \
errno = 0; \
expr; \
} while G_UNLIKELY (errno == EINTR);
GQuark gdm_common_error_quark (void);
#define GDM_COMMON_ERROR gdm_common_error_quark()
typedef char * (*GdmExpandVarFunc) (const char *var,
gpointer user_data);
G_BEGIN_DECLS
int gdm_wait_on_pid (int pid);
int gdm_wait_on_and_disown_pid (int pid,
int timeout);
int gdm_signal_pid (int pid,
int signal);
gboolean gdm_get_pwent_for_name (const char *name,
struct passwd **pwentp);
gboolean gdm_clear_close_on_exec_flag (int fd);
const char * gdm_make_temp_dir (char *template);
char *gdm_generate_random_bytes (gsize size,
GError **error);
+gboolean gdm_get_login_window_session_id (const char *seat_id,
+ char **session_id);
gboolean gdm_goto_login_session (GError **error);
GPtrArray *gdm_get_script_environment (const char *username,
const char *display_name,
const char *display_hostname,
const char *display_x11_authority_file);
gboolean gdm_run_script (const char *dir,
const char *username,
const char *display_name,
const char *display_hostname,
const char *display_x11_authority_file);
gboolean gdm_shell_var_is_valid_char (char c,
gboolean first);
char * gdm_shell_expand (const char *str,
GdmExpandVarFunc expand_func,
gpointer user_data);
G_END_DECLS
#endif /* _GDM_COMMON_H */
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 7a5554e9d..375ef6f80 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1444,61 +1444,61 @@ get_login_window_session_id (const char *seat_id,
ret = TRUE;
free (service_id);
goto out;
}
free (service_id);
}
*session_id = NULL;
ret = FALSE;
out:
if (sessions) {
for (i = 0; sessions[i]; i ++) {
free (sessions[i]);
}
free (sessions);
}
return ret;
}
static void
activate_login_window_session_on_seat (GdmManager *self,
const char *seat_id)
{
char *session_id;
- if (!get_login_window_session_id (seat_id, &session_id)) {
+ if (!gdm_get_login_window_session_id (seat_id, &session_id)) {
return;
}
if (session_id) {
activate_session_id (self, seat_id, session_id);
g_free (session_id);
}
}
static void
maybe_activate_other_session (GdmManager *self,
GdmDisplay *old_display)
{
char *seat_id = NULL;
char *session_id;
int ret;
g_object_get (G_OBJECT (old_display),
"seat-id", &seat_id,
NULL);
ret = sd_seat_get_active (seat_id, &session_id, NULL);
if (ret == 0) {
GdmDisplay *display;
display = gdm_display_store_find (self->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
@@ -2082,61 +2082,61 @@ on_user_session_exited (GdmSession *session,
static void
on_user_session_died (GdmSession *session,
int signal_number,
GdmManager *manager)
{
g_debug ("GdmManager: session died with signal %s", strsignal (signal_number));
remove_user_session (manager, session);
}
static char *
get_display_device (GdmManager *manager,
GdmDisplay *display)
{
/* systemd finds the display device out on its own based on the display */
return NULL;
}
static void
on_session_reauthenticated (GdmSession *session,
const char *service_name,
GdmManager *manager)
{
gboolean fail_if_already_switched = FALSE;
if (gdm_session_get_display_mode (session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
const char *seat_id;
char *session_id;
seat_id = gdm_session_get_display_seat_id (session);
- if (get_login_window_session_id (seat_id, &session_id)) {
+ if (gdm_get_login_window_session_id (seat_id, &session_id)) {
GdmDisplay *display = gdm_display_store_find (manager->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
if (display != NULL) {
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
}
g_free (session_id);
}
}
/* There should already be a session running, so jump to its
* VT. In the event we're already on the right VT, (i.e. user
* used an unlock screen instead of a user switched login screen),
* then silently succeed and unlock the session.
*/
switch_to_compatible_user_session (manager, session, fail_if_already_switched);
}
static void
on_session_client_ready_for_session_to_start (GdmSession *session,
const char *service_name,
gboolean client_is_ready,
GdmManager *manager)
{
gboolean waiting_to_start_user_session;
if (client_is_ready) {
--
2.27.0

View File

@ -1,401 +0,0 @@
From 9d8e72ea9171566e9d74caaf28c8b5933ef34874 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 2 Aug 2018 14:00:46 -0400
Subject: [PATCH 08/51] common: dedupe activate_session_id
Right now there are three copies of activate_session_id.
This commit consolidates the code to gdm-common.c
---
common/gdm-common.c | 10 +++++-----
common/gdm-common.h | 6 ++++++
daemon/gdm-manager.c | 33 +--------------------------------
3 files changed, 12 insertions(+), 37 deletions(-)
diff --git a/common/gdm-common.c b/common/gdm-common.c
index 00daf0df8..59317a889 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -335,64 +335,64 @@ static gboolean
create_transient_display (GDBusConnection *connection,
GError **error)
{
GError *local_error = NULL;
GVariant *reply;
const char *value;
reply = g_dbus_connection_call_sync (connection,
GDM_DBUS_NAME,
GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
"CreateTransientDisplay",
NULL, /* parameters */
G_VARIANT_TYPE ("(o)"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, &local_error);
if (reply == NULL) {
g_warning ("Unable to create transient display: %s", local_error->message);
g_propagate_error (error, local_error);
return FALSE;
}
g_variant_get (reply, "(&o)", &value);
g_debug ("Started %s", value);
g_variant_unref (reply);
return TRUE;
}
-static gboolean
-activate_session_id (GDBusConnection *connection,
- const char *seat_id,
- const char *session_id)
+gboolean
+gdm_activate_session_by_id (GDBusConnection *connection,
+ const char *seat_id,
+ const char *session_id)
{
GError *local_error = NULL;
GVariant *reply;
reply = g_dbus_connection_call_sync (connection,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ActivateSessionOnSeat",
g_variant_new ("(ss)", session_id, seat_id),
NULL,
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, &local_error);
if (reply == NULL) {
g_warning ("Unable to activate session: %s", local_error->message);
g_error_free (local_error);
return FALSE;
}
g_variant_unref (reply);
return TRUE;
}
gboolean
gdm_get_login_window_session_id (const char *seat_id,
char **session_id)
{
gboolean ret;
@@ -512,61 +512,61 @@ goto_login_session (GDBusConnection *connection,
res = sd_session_get_seat (our_session, &seat_id);
free (our_session);
if (res < 0) {
g_debug ("failed to determine own seat: %s", strerror (-res));
g_set_error (error, GDM_COMMON_ERROR, 0, _("Could not identify the current seat."));
return FALSE;
}
res = sd_seat_can_multi_session (seat_id);
if (res < 0) {
free (seat_id);
g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to determine whether to switch to an existing login screen or start up a new login screen."));
return FALSE;
}
if (res == 0) {
free (seat_id);
g_set_error (error, GDM_COMMON_ERROR, 0, _("The system is unable to start up a new login screen."));
return FALSE;
}
res = gdm_get_login_window_session_id (seat_id, &session_id);
if (res && session_id != NULL) {
- res = activate_session_id (connection, seat_id, session_id);
+ res = gdm_activate_session_by_id (connection, seat_id, session_id);
if (res) {
ret = TRUE;
}
}
if (! ret && g_strcmp0 (seat_id, "seat0") == 0) {
res = create_transient_display (connection, error);
if (res) {
ret = TRUE;
}
}
free (seat_id);
g_free (session_id);
return ret;
}
gboolean
gdm_goto_login_session (GError **error)
{
GError *local_error;
GDBusConnection *connection;
local_error = NULL;
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local_error);
if (connection == NULL) {
g_debug ("Failed to connect to the D-Bus daemon: %s", local_error->message);
g_propagate_error (error, local_error);
diff --git a/common/gdm-common.h b/common/gdm-common.h
index c9cbd9c48..3fbf07653 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -1,78 +1,84 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef _GDM_COMMON_H
#define _GDM_COMMON_H
#include <glib-unix.h>
+#include <gio/gio.h>
+
#include <pwd.h>
#include <errno.h>
#define VE_IGNORE_EINTR(expr) \
do { \
errno = 0; \
expr; \
} while G_UNLIKELY (errno == EINTR);
GQuark gdm_common_error_quark (void);
#define GDM_COMMON_ERROR gdm_common_error_quark()
typedef char * (*GdmExpandVarFunc) (const char *var,
gpointer user_data);
G_BEGIN_DECLS
int gdm_wait_on_pid (int pid);
int gdm_wait_on_and_disown_pid (int pid,
int timeout);
int gdm_signal_pid (int pid,
int signal);
gboolean gdm_get_pwent_for_name (const char *name,
struct passwd **pwentp);
gboolean gdm_clear_close_on_exec_flag (int fd);
const char * gdm_make_temp_dir (char *template);
char *gdm_generate_random_bytes (gsize size,
GError **error);
gboolean gdm_get_login_window_session_id (const char *seat_id,
char **session_id);
gboolean gdm_goto_login_session (GError **error);
GPtrArray *gdm_get_script_environment (const char *username,
const char *display_name,
const char *display_hostname,
const char *display_x11_authority_file);
gboolean gdm_run_script (const char *dir,
const char *username,
const char *display_name,
const char *display_hostname,
const char *display_x11_authority_file);
gboolean gdm_shell_var_is_valid_char (char c,
gboolean first);
char * gdm_shell_expand (const char *str,
GdmExpandVarFunc expand_func,
gpointer user_data);
+gboolean gdm_activate_session_by_id (GDBusConnection *connection,
+ const char *seat_id,
+ const char *session_id);
+
G_END_DECLS
#endif /* _GDM_COMMON_H */
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 375ef6f80..617ee36f0 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -267,91 +267,60 @@ lookup_by_session_id (const char *id,
static gboolean
is_login_session (GdmManager *self,
const char *session_id,
GError **error)
{
char *session_class = NULL;
int ret;
ret = sd_session_get_class (session_id, &session_class);
if (ret < 0) {
g_set_error (error,
GDM_DISPLAY_ERROR,
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
"Error getting class for session id %s from systemd: %s",
session_id,
g_strerror (-ret));
return FALSE;
}
if (g_strcmp0 (session_class, "greeter") != 0) {
g_free (session_class);
return FALSE;
}
g_free (session_class);
return TRUE;
}
-static gboolean
-activate_session_id (GdmManager *manager,
- const char *seat_id,
- const char *session_id)
-{
- GError *error = NULL;
- GVariant *reply;
-
- reply = g_dbus_connection_call_sync (manager->priv->connection,
- "org.freedesktop.login1",
- "/org/freedesktop/login1",
- "org.freedesktop.login1.Manager",
- "ActivateSessionOnSeat",
- g_variant_new ("(ss)", session_id, seat_id),
- NULL, /* expected reply */
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- &error);
- if (reply == NULL) {
- g_debug ("GdmManager: logind 'ActivateSessionOnSeat' %s raised:\n %s\n\n",
- g_dbus_error_get_remote_error (error), error->message);
- g_error_free (error);
- return FALSE;
- }
-
- g_variant_unref (reply);
-
- return TRUE;
-}
-
static gboolean
session_unlock (GdmManager *manager,
const char *ssid)
{
GError *error = NULL;
GVariant *reply;
g_debug ("Unlocking session %s", ssid);
reply = g_dbus_connection_call_sync (manager->priv->connection,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"UnlockSession",
g_variant_new ("(s)", ssid),
NULL, /* expected reply */
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL,
&error);
if (reply == NULL) {
g_debug ("GdmManager: logind 'UnlockSession' %s raised:\n %s\n\n",
g_dbus_error_get_remote_error (error), error->message);
g_error_free (error);
return FALSE;
}
g_variant_unref (reply);
return TRUE;
@@ -627,61 +596,61 @@ switch_to_compatible_user_session (GdmManager *manager,
ret = FALSE;
username = gdm_session_get_username (session);
seat_id = gdm_session_get_display_seat_id (session);
if (!fail_if_already_switched)
ssid_to_activate = gdm_session_get_session_id (session);
if (ssid_to_activate == NULL) {
if (!seat_id || !sd_seat_can_multi_session (seat_id)) {
g_debug ("GdmManager: unable to activate existing sessions from login screen unless on seat0");
goto out;
}
if (!fail_if_already_switched) {
session = NULL;
}
existing_session = find_session_for_user_on_seat (manager, username, seat_id, session);
if (existing_session != NULL) {
ssid_to_activate = gdm_session_get_session_id (existing_session);
}
}
if (ssid_to_activate == NULL) {
goto out;
}
if (seat_id != NULL) {
- res = activate_session_id (manager, seat_id, ssid_to_activate);
+ res = gdm_activate_session_by_id (manager->priv->connection, seat_id, ssid_to_activate);
if (! res) {
g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate);
goto out;
}
}
res = session_unlock (manager, ssid_to_activate);
if (!res) {
/* this isn't fatal */
g_debug ("GdmManager: unable to unlock session: %s", ssid_to_activate);
}
ret = TRUE;
out:
return ret;
}
static GdmDisplay *
get_display_for_user_session (GdmSession *session)
{
return g_object_get_data (G_OBJECT (session), "gdm-display");
}
static GdmSession *
get_user_session_for_display (GdmDisplay *display)
{
if (display == NULL) {
return NULL;
}
--
2.27.0

View File

@ -1,103 +0,0 @@
From 5bc19a4eb6de02ba549252026911dcce86e0fc21 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 22 Jun 2018 14:44:11 -0400
Subject: [PATCH 09/51] manager: plug leak in maybe_activate_other_session
The function asks logind what the currently active session is on the
given seat. It then leaks the response.
This commit plugs the leak.
---
daemon/gdm-manager.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 617ee36f0..a4dad92ee 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1428,79 +1428,81 @@ out:
free (sessions[i]);
}
free (sessions);
}
return ret;
}
static void
activate_login_window_session_on_seat (GdmManager *self,
const char *seat_id)
{
char *session_id;
if (!gdm_get_login_window_session_id (seat_id, &session_id)) {
return;
}
if (session_id) {
activate_session_id (self, seat_id, session_id);
g_free (session_id);
}
}
static void
maybe_activate_other_session (GdmManager *self,
GdmDisplay *old_display)
{
char *seat_id = NULL;
- char *session_id;
+ char *session_id = NULL;
int ret;
g_object_get (G_OBJECT (old_display),
"seat-id", &seat_id,
NULL);
ret = sd_seat_get_active (seat_id, &session_id, NULL);
if (ret == 0) {
GdmDisplay *display;
display = gdm_display_store_find (self->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
if (display == NULL) {
activate_login_window_session_on_seat (self, seat_id);
}
+
+ g_free (session_id);
}
g_free (seat_id);
}
static const char *
get_username_for_greeter_display (GdmManager *manager,
GdmDisplay *display)
{
gboolean doing_initial_setup = FALSE;
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
NULL);
if (doing_initial_setup) {
return INITIAL_SETUP_USERNAME;
} else {
return GDM_USERNAME;
}
}
static void
set_up_automatic_login_session (GdmManager *manager,
GdmDisplay *display)
{
GdmSession *session;
char *display_session_type = NULL;
gboolean is_initial;
--
2.27.0

View File

@ -1,92 +0,0 @@
From 2ec1b65c7bc2cefeabbd9a7a3a50436e1233804c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 22 Jun 2018 14:55:39 -0400
Subject: [PATCH 10/51] manager: start login screen if old one is finished
Since commit 22c332ba we try to start a login screen if we end up
on an empty VT and there isn't one running.
Unfortunately the check for "is on an empty VT" is a little busted.
It counts the VT has non-empty if there's a display associated with
it, even if that display is in the FINISHED state about to be
reaped.
That means, in some cases, we'll still leave the user on an empty
VT with no login screen.
This commit addresses the problem by explicitly checking for
FINISHED displays, and proceeding even in their presense.
---
daemon/gdm-manager.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index a4dad92ee..a6f13dec7 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1444,61 +1444,61 @@ activate_login_window_session_on_seat (GdmManager *self,
return;
}
if (session_id) {
activate_session_id (self, seat_id, session_id);
g_free (session_id);
}
}
static void
maybe_activate_other_session (GdmManager *self,
GdmDisplay *old_display)
{
char *seat_id = NULL;
char *session_id = NULL;
int ret;
g_object_get (G_OBJECT (old_display),
"seat-id", &seat_id,
NULL);
ret = sd_seat_get_active (seat_id, &session_id, NULL);
if (ret == 0) {
GdmDisplay *display;
display = gdm_display_store_find (self->priv->display_store,
lookup_by_session_id,
(gpointer) session_id);
- if (display == NULL) {
+ if (display == NULL || gdm_display_get_status (display) == GDM_DISPLAY_FINISHED) {
activate_login_window_session_on_seat (self, seat_id);
}
g_free (session_id);
}
g_free (seat_id);
}
static const char *
get_username_for_greeter_display (GdmManager *manager,
GdmDisplay *display)
{
gboolean doing_initial_setup = FALSE;
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
NULL);
if (doing_initial_setup) {
return INITIAL_SETUP_USERNAME;
} else {
return GDM_USERNAME;
}
}
static void
set_up_automatic_login_session (GdmManager *manager,
GdmDisplay *display)
{
--
2.27.0

View File

@ -1,127 +0,0 @@
From 67d29b19ff4e53d58879b14c2e79a3bda419576f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 22 Jun 2018 15:26:03 -0400
Subject: [PATCH 11/51] manager: don't bail if session disappears out from
under us
It's entirely possible for a session returned by
sd_seat_get_sessions to disappear immediately after the
sd_seat_get_sessions call returns. This is especially
likely at logout time where the session will briefly be
in the "closing" state before getting reaped.
If that happens when we're looking for a greeter session, we
stop looking for a greeter session and bail out all confused.
This commit fixes the confusion by gracefully handling the
session disappearing by just proceeding to the next session
in the list.
---
daemon/gdm-manager.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index a6f13dec7..ede22e771 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1349,87 +1349,97 @@ maybe_start_pending_initial_login (GdmManager *manager,
g_free (user_session_seat_id);
}
static gboolean
get_login_window_session_id (const char *seat_id,
char **session_id)
{
gboolean ret;
int res, i;
char **sessions;
char *service_id;
char *service_class;
char *state;
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
if (res < 0) {
g_debug ("Failed to determine sessions: %s", strerror (-res));
return FALSE;
}
if (sessions == NULL || sessions[0] == NULL) {
*session_id = NULL;
ret = FALSE;
goto out;
}
for (i = 0; sessions[i]; i ++) {
res = sd_session_get_class (sessions[i], &service_class);
if (res < 0) {
+ if (res == -ENOENT) {
+ free (service_class);
+ continue;
+ }
+
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_class, "greeter") != 0) {
free (service_class);
continue;
}
free (service_class);
ret = sd_session_get_state (sessions[i], &state);
if (ret < 0) {
+ if (res == -ENOENT)
+ continue;
+
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (g_strcmp0 (state, "closing") == 0) {
free (state);
continue;
}
free (state);
res = sd_session_get_service (sessions[i], &service_id);
if (res < 0) {
+ if (res == -ENOENT)
+ continue;
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_id, "gdm-launch-environment") == 0) {
*session_id = g_strdup (sessions[i]);
ret = TRUE;
free (service_id);
goto out;
}
free (service_id);
}
*session_id = NULL;
ret = FALSE;
out:
if (sessions) {
for (i = 0; sessions[i]; i ++) {
free (sessions[i]);
}
free (sessions);
}
return ret;
}
--
2.27.0

View File

@ -1,563 +0,0 @@
From 9a3e9cb9a6bbf68ed6eb9f13d143a63af940f3ae Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 30 Jul 2018 16:21:29 -0400
Subject: [PATCH 12/51] daemon: try harder to get to a login screen at logout
commit 22c332ba and some follow up commits try to ensure the
user never stays on a blank VT by jumping to a login screen in
the event they'd end up on one.
Unfortunately, that part of the code can't start a login screen
if there's not one running at all.
This commit moves the code to GdmLocalDisplyFactory where the
login screens are created, so users won't end up on a blank
VT even if no login screen is yet running.
---
daemon/gdm-local-display-factory.c | 36 +++++++-
daemon/gdm-manager.c | 143 -----------------------------
2 files changed, 31 insertions(+), 148 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index e52360a56..0e454c880 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -1,60 +1,62 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
*
* Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <gio/gio.h>
+#include <systemd/sd-login.h>
+
#include "gdm-common.h"
#include "gdm-manager.h"
#include "gdm-display-factory.h"
#include "gdm-local-display-factory.h"
#include "gdm-local-display-factory-glue.h"
#include "gdm-settings-keys.h"
#include "gdm-settings-direct.h"
#include "gdm-display-store.h"
#include "gdm-local-display.h"
#include "gdm-legacy-display.h"
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
#define MAX_DISPLAY_FAILURES 5
struct GdmLocalDisplayFactoryPrivate
{
GdmDBusLocalDisplayFactory *skeleton;
GDBusConnection *connection;
GHashTable *used_display_numbers;
/* FIXME: this needs to be per seat? */
guint num_failures;
guint seat_new_id;
@@ -240,174 +242,198 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
store_display (factory, display);
if (! gdm_display_manage (display)) {
display = NULL;
goto out;
}
if (! gdm_display_get_id (display, id, NULL)) {
display = NULL;
goto out;
}
ret = TRUE;
out:
/* ref either held by store or not at all */
g_object_unref (display);
return ret;
}
static void
on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory)
{
int status;
int num;
char *seat_id = NULL;
char *session_type = NULL;
+ char *session_class = NULL;
gboolean is_initial = TRUE;
gboolean is_local = TRUE;
num = -1;
gdm_display_get_x11_display_number (display, &num, NULL);
g_object_get (display,
"seat-id", &seat_id,
"is-initial", &is_initial,
"is-local", &is_local,
"session-type", &session_type,
+ "session-class", &session_class,
NULL);
status = gdm_display_get_status (display);
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
switch (status) {
case GDM_DISPLAY_FINISHED:
/* remove the display number from factory->priv->used_display_numbers
so that it may be reused */
if (num != -1) {
g_hash_table_remove (factory->priv->used_display_numbers, GUINT_TO_POINTER (num));
}
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
/* if this is a local display, do a full resync. Only
* seats without displays will get created anyway. This
* ensures we get a new login screen when the user logs out,
* if there isn't one.
*/
- if (is_local) {
+ if (is_local && g_strcmp0 (session_class, "greeter") != 0) {
/* reset num failures */
factory->priv->num_failures = 0;
gdm_local_display_factory_sync_seats (factory);
}
break;
case GDM_DISPLAY_FAILED:
/* leave the display number in factory->priv->used_display_numbers
so that it doesn't get reused */
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
/* Create a new equivalent display if it was static */
if (is_local) {
factory->priv->num_failures++;
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
/* oh shit */
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
} else {
#ifdef ENABLE_WAYLAND_SUPPORT
if (g_strcmp0 (session_type, "wayland") == 0) {
g_free (session_type);
session_type = NULL;
/* workaround logind race for now
* bug 1643874
*/
g_usleep (2 * G_USEC_PER_SEC);
}
#endif
create_display (factory, seat_id, session_type, is_initial);
}
}
break;
case GDM_DISPLAY_UNMANAGED:
break;
case GDM_DISPLAY_PREPARED:
break;
case GDM_DISPLAY_MANAGED:
break;
default:
g_assert_not_reached ();
break;
}
g_free (seat_id);
g_free (session_type);
+ g_free (session_class);
}
static gboolean
lookup_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
static GdmDisplay *
create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
+ char *active_session_id = NULL;
+ int ret;
- /* Ensure we don't create the same display more than once */
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
- if (display != NULL) {
- return NULL;
+
+ ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
+
+ if (ret == 0) {
+ char *login_session_id = NULL;
+
+ /* If we already have a login window, switch to it */
+ if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
+ if (g_strcmp0 (active_session_id, login_session_id) != 0) {
+ gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
+ }
+ g_clear_pointer (&login_session_id, g_free);
+ g_clear_pointer (&active_session_id, g_free);
+ return NULL;
+ }
+ g_clear_pointer (&active_session_id, g_free);
+ } else {
+ /* Ensure we don't create the same display more than once */
+ display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
+
+ if (display != NULL) {
+ return NULL;
+ }
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
g_object_set (display, "seat-id", seat_id, NULL);
g_object_set (display, "is-initial", initial, NULL);
store_display (factory, display);
/* let store own the ref */
g_object_unref (display);
if (! gdm_display_manage (display)) {
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index ede22e771..80f60d24c 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1322,202 +1322,60 @@ maybe_start_pending_initial_login (GdmManager *manager,
char *user_session_seat_id = NULL;
/* There may be a user session waiting to be started.
* This would happen if we couldn't start it earlier because
* the login screen X server was coming up and two X servers
* can't be started on the same seat at the same time.
*/
if (manager->priv->initial_login_operation == NULL) {
return;
}
operation = manager->priv->initial_login_operation;
g_object_get (G_OBJECT (greeter_display),
"seat-id", &greeter_seat_id,
NULL);
g_object_get (G_OBJECT (operation->session),
"display-seat-id", &user_session_seat_id,
NULL);
if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) {
start_user_session (manager, operation);
manager->priv->initial_login_operation = NULL;
}
g_free (greeter_seat_id);
g_free (user_session_seat_id);
}
-static gboolean
-get_login_window_session_id (const char *seat_id,
- char **session_id)
-{
- gboolean ret;
- int res, i;
- char **sessions;
- char *service_id;
- char *service_class;
- char *state;
-
- res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
- if (res < 0) {
- g_debug ("Failed to determine sessions: %s", strerror (-res));
- return FALSE;
- }
-
- if (sessions == NULL || sessions[0] == NULL) {
- *session_id = NULL;
- ret = FALSE;
- goto out;
- }
-
- for (i = 0; sessions[i]; i ++) {
-
- res = sd_session_get_class (sessions[i], &service_class);
- if (res < 0) {
- if (res == -ENOENT) {
- free (service_class);
- continue;
- }
-
- g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
- ret = FALSE;
- goto out;
- }
-
- if (strcmp (service_class, "greeter") != 0) {
- free (service_class);
- continue;
- }
-
- free (service_class);
-
- ret = sd_session_get_state (sessions[i], &state);
- if (ret < 0) {
- if (res == -ENOENT)
- continue;
-
- g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
- ret = FALSE;
- goto out;
- }
-
- if (g_strcmp0 (state, "closing") == 0) {
- free (state);
- continue;
- }
- free (state);
-
- res = sd_session_get_service (sessions[i], &service_id);
- if (res < 0) {
- if (res == -ENOENT)
- continue;
- g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
- ret = FALSE;
- goto out;
- }
-
- if (strcmp (service_id, "gdm-launch-environment") == 0) {
- *session_id = g_strdup (sessions[i]);
- ret = TRUE;
-
- free (service_id);
- goto out;
- }
-
- free (service_id);
- }
-
- *session_id = NULL;
- ret = FALSE;
-
-out:
- if (sessions) {
- for (i = 0; sessions[i]; i ++) {
- free (sessions[i]);
- }
-
- free (sessions);
- }
-
- return ret;
-}
-
-static void
-activate_login_window_session_on_seat (GdmManager *self,
- const char *seat_id)
-{
- char *session_id;
-
- if (!gdm_get_login_window_session_id (seat_id, &session_id)) {
- return;
- }
-
- if (session_id) {
- activate_session_id (self, seat_id, session_id);
- g_free (session_id);
- }
-}
-
-static void
-maybe_activate_other_session (GdmManager *self,
- GdmDisplay *old_display)
-{
- char *seat_id = NULL;
- char *session_id = NULL;
- int ret;
-
- g_object_get (G_OBJECT (old_display),
- "seat-id", &seat_id,
- NULL);
-
- ret = sd_seat_get_active (seat_id, &session_id, NULL);
-
- if (ret == 0) {
- GdmDisplay *display;
-
- display = gdm_display_store_find (self->priv->display_store,
- lookup_by_session_id,
- (gpointer) session_id);
-
- if (display == NULL || gdm_display_get_status (display) == GDM_DISPLAY_FINISHED) {
- activate_login_window_session_on_seat (self, seat_id);
- }
-
- g_free (session_id);
- }
-
- g_free (seat_id);
-}
-
static const char *
get_username_for_greeter_display (GdmManager *manager,
GdmDisplay *display)
{
gboolean doing_initial_setup = FALSE;
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
NULL);
if (doing_initial_setup) {
return INITIAL_SETUP_USERNAME;
} else {
return GDM_USERNAME;
}
}
static void
set_up_automatic_login_session (GdmManager *manager,
GdmDisplay *display)
{
GdmSession *session;
char *display_session_type = NULL;
gboolean is_initial;
/* 0 is root user; since the daemon talks to the session object
* directly, itself, for automatic login
*/
session = create_user_session_for_display (manager, display, 0);
@@ -1709,61 +1567,60 @@ on_display_status_changed (GdmDisplay *display,
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
char *session_class;
g_object_get (display,
"session-class", &session_class,
NULL);
if (g_strcmp0 (session_class, "greeter") == 0)
set_up_session (manager, display);
g_free (session_class);
}
if (status == GDM_DISPLAY_MANAGED) {
greeter_display_started (manager, display);
}
break;
case GDM_DISPLAY_FAILED:
case GDM_DISPLAY_UNMANAGED:
case GDM_DISPLAY_FINISHED:
#ifdef WITH_PLYMOUTH
if (quit_plymouth) {
plymouth_quit_without_transition ();
manager->priv->plymouth_is_running = FALSE;
}
#endif
if (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0) {
manager->priv->ran_once = TRUE;
}
maybe_start_pending_initial_login (manager, display);
- maybe_activate_other_session (manager, display);
break;
default:
break;
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmManager *manager)
{
char *id;
gdm_display_get_id (display, &id, NULL);
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
g_free (id);
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
}
static void
destroy_start_user_session_operation (StartUserSessionOperation *operation)
{
g_object_set_data (G_OBJECT (operation->session),
"start-user-session-operation",
NULL);
g_object_unref (operation->session);
--
2.27.0

View File

@ -1,87 +0,0 @@
From 299a0981f4e9fc02716d64abf5e5e692e2ad2951 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 3 Aug 2018 16:50:36 -0400
Subject: [PATCH 13/51] local-display-factory: ensure non-seat0 codepath
doesn't affect seat0
create_display currently bails in some cases if any display is running
on the seat. That's the right thing to do on seats other than seat0,
but wrong for seat0 (which an have multiple sessions at the same
time).
To ensure we never hit the case for seat0, add a call to check if
the passed seat is multi-session capable.
---
daemon/gdm-local-display-factory.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 0e454c880..7f7735ca1 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -373,61 +373,61 @@ lookup_by_seat_id (const char *id,
}
static GdmDisplay *
create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
char *active_session_id = NULL;
int ret;
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
if (ret == 0) {
char *login_session_id = NULL;
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
if (g_strcmp0 (active_session_id, login_session_id) != 0) {
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
}
g_clear_pointer (&login_session_id, g_free);
g_clear_pointer (&active_session_id, g_free);
return NULL;
}
g_clear_pointer (&active_session_id, g_free);
- } else {
+ } else if (!sd_seat_can_multi_session (seat_id)) {
/* Ensure we don't create the same display more than once */
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
if (display != NULL) {
return NULL;
}
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
g_object_set (display, "seat-id", seat_id, NULL);
g_object_set (display, "is-initial", initial, NULL);
--
2.27.0

View File

@ -1,369 +0,0 @@
From 08f5f88ca6fb0edfc94af4c85912484b6048691b Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 2 Aug 2018 15:06:09 -0400
Subject: [PATCH 14/51] daemon: kill and restart greeter on demand under
wayland
Right now we leave the greeter alive after the user logs in.
This is for two reasons:
1) When the greeter is running Xorg, there's no way to kill
it when it's running on an inactive VT (X jumps to the foreground
when being killed)
2) The greeter, in a way, provides a securepath for unlock.
Users in theory could know that by hitting ctrl-alt-f1 to secure
attention, the login screen presented is not spoofed.
Since we use wayland by default, 1 isn't that much of a concern,
and 2 is a bit of niche feature that most users probably haven't
considered.
And there's a huge downside to keeping the greeter alive: it uses
a very large amount of memory.
This commit changes GDM to kill the login screen when switching
away from the login screen's VT and restarting it when switching
back.
Based heavily on work by Hans de Goede <hdegoede@redhat.com>
Closes: https://gitlab.gnome.org/GNOME/gdm/issues/222
---
daemon/gdm-local-display-factory.c | 167 +++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 7f7735ca1..4ae656ab3 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -34,60 +34,65 @@
#include "gdm-manager.h"
#include "gdm-display-factory.h"
#include "gdm-local-display-factory.h"
#include "gdm-local-display-factory-glue.h"
#include "gdm-settings-keys.h"
#include "gdm-settings-direct.h"
#include "gdm-display-store.h"
#include "gdm-local-display.h"
#include "gdm-legacy-display.h"
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
#define MAX_DISPLAY_FAILURES 5
struct GdmLocalDisplayFactoryPrivate
{
GdmDBusLocalDisplayFactory *skeleton;
GDBusConnection *connection;
GHashTable *used_display_numbers;
/* FIXME: this needs to be per seat? */
guint num_failures;
guint seat_new_id;
guint seat_removed_id;
+
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ char *tty_of_active_vt;
+ guint active_vt_watch_id;
+#endif
};
enum {
PROP_0,
};
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
static void gdm_local_display_factory_finalize (GObject *object);
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial_display);
static void on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory);
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
static gpointer local_display_factory_object = NULL;
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
GQuark
gdm_local_display_factory_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_local_display_factory_error");
@@ -507,98 +512,260 @@ gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
static void
on_seat_new (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *seat;
g_variant_get (parameters, "(&s&o)", &seat, NULL);
create_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat, NULL, FALSE);
}
static void
on_seat_removed (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *seat;
g_variant_get (parameters, "(&s&o)", &seat, NULL);
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
}
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+static gboolean
+lookup_by_session_id (const char *id,
+ GdmDisplay *display,
+ gpointer user_data)
+{
+ const char *looking_for = user_data;
+ const char *current;
+
+ current = gdm_display_get_session_id (display);
+ return g_strcmp0 (current, looking_for) == 0;
+}
+
+static void
+maybe_stop_greeter_display (GdmDisplay *display)
+{
+ g_autofree char *display_session_type = NULL;
+
+ if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
+ return;
+
+ g_object_get (G_OBJECT (display),
+ "session-type", &display_session_type,
+ NULL);
+
+ /* we can only stop greeter for wayland sessions, since
+ * X server would jump back on exit */
+ if (g_strcmp0 (display_session_type, "wayland") != 0)
+ return;
+
+ gdm_display_stop_greeter_session (display);
+ gdm_display_unmanage (display);
+ gdm_display_finish (display);
+}
+
+static gboolean
+on_vt_changed (GIOChannel *source,
+ GIOCondition condition,
+ GdmLocalDisplayFactory *factory)
+{
+ GIOStatus status;
+ static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
+ g_autofree char *tty_of_previous_vt = NULL;
+ g_autofree char *tty_of_active_vt = NULL;
+ g_autofree char *login_session_id = NULL;
+ g_autofree char *active_session_id = NULL;
+ const char *session_type = NULL;
+ int ret;
+
+ g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
+
+ if (condition & G_IO_PRI) {
+ g_autoptr (GError) error = NULL;
+ status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
+
+ if (error != NULL) {
+ g_warning ("could not read active VT from kernel: %s", error->message);
+ }
+ switch (status) {
+ case G_IO_STATUS_ERROR:
+ return G_SOURCE_REMOVE;
+ case G_IO_STATUS_EOF:
+ return G_SOURCE_REMOVE;
+ case G_IO_STATUS_AGAIN:
+ return G_SOURCE_CONTINUE;
+ case G_IO_STATUS_NORMAL:
+ break;
+ }
+ }
+
+ if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
+ return G_SOURCE_REMOVE;
+
+ if (tty_of_active_vt == NULL)
+ return G_SOURCE_CONTINUE;
+
+ g_strchomp (tty_of_active_vt);
+
+ /* don't do anything if we're on the same VT we were before */
+ if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0)
+ return G_SOURCE_CONTINUE;
+
+ tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
+ factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
+
+ /* if the old VT was running a wayland login screen kill it
+ */
+ if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
+ unsigned int vt;
+
+ ret = sd_session_get_vt (login_session_id, &vt);
+ if (ret == 0 && vt != 0) {
+ g_autofree char *tty_of_login_window_vt = NULL;
+
+ tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
+
+ if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
+ GdmDisplayStore *store;
+ GdmDisplay *display;
+
+ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+ display = gdm_display_store_find (store,
+ lookup_by_session_id,
+ (gpointer) login_session_id);
+
+ if (display != NULL)
+ maybe_stop_greeter_display (display);
+ }
+ }
+ }
+
+ /* if user jumped back to initial vt and it's empty put a login screen
+ * on it (unless a login screen is already running elsewhere, then
+ * jump to that login screen)
+ */
+ if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
+ return G_SOURCE_CONTINUE;
+ }
+
+ ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
+
+ if (ret == 0) {
+ g_autofree char *state = NULL;
+ ret = sd_session_get_state (active_session_id, &state);
+
+ /* if there's something already running on the active VT then bail */
+ if (ret == 0 && g_strcmp0 (state, "closing") != 0)
+ return G_SOURCE_CONTINUE;
+ }
+
+ if (gdm_local_display_factory_use_wayland ())
+ session_type = "wayland";
+
+ create_display (factory, "seat0", session_type, TRUE);
+
+ return G_SOURCE_CONTINUE;
+}
+#endif
+
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
+ g_autoptr (GIOChannel) io_channel = NULL;
+
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatNew",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_new,
g_object_ref (factory),
g_object_unref);
factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatRemoved",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_removed,
g_object_ref (factory),
g_object_unref);
+
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
+
+ if (io_channel != NULL) {
+ factory->priv->active_vt_watch_id =
+ g_io_add_watch (io_channel,
+ G_IO_PRI,
+ (GIOFunc)
+ on_vt_changed,
+ factory);
+ }
+#endif
}
static void
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
{
if (factory->priv->seat_new_id) {
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
factory->priv->seat_new_id);
factory->priv->seat_new_id = 0;
}
if (factory->priv->seat_removed_id) {
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
factory->priv->seat_removed_id);
factory->priv->seat_removed_id = 0;
}
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ if (factory->priv->active_vt_watch_id) {
+ g_source_remove (factory->priv->active_vt_watch_id);
+ factory->priv->active_vt_watch_id = 0;
+ }
+
+ g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
+#endif
}
static void
on_display_added (GdmDisplayStore *display_store,
const char *id,
GdmLocalDisplayFactory *factory)
{
GdmDisplay *display;
display = gdm_display_store_lookup (display_store, id);
if (display != NULL) {
g_signal_connect_object (display, "notify::status",
G_CALLBACK (on_display_status_changed),
factory,
0);
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmLocalDisplayFactory *factory)
{
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory);
g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
}
--
2.27.0

View File

@ -1,235 +0,0 @@
From 59533722f1749d4e71360c5d717a18006c1f64c0 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Aug 2018 13:55:06 -0400
Subject: [PATCH 15/51] local-display-factory: add more debug messages to new
vt handling code
commit c0188a7030 added some complex code for starting and stopping
the login screen based on VT changes.
That code currently has zero debug statements in it making it trickier
than necessary to debug.
This commit sprinkles some g_debug's throughout the function.
---
daemon/gdm-local-display-factory.c | 44 ++++++++++++++++++++++++------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 4ae656ab3..2a2259f2a 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -530,175 +530,201 @@ on_seat_removed (GDBusConnection *connection,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *seat;
g_variant_get (parameters, "(&s&o)", &seat, NULL);
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
static gboolean
lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
const char *current;
current = gdm_display_get_session_id (display);
return g_strcmp0 (current, looking_for) == 0;
}
static void
maybe_stop_greeter_display (GdmDisplay *display)
{
g_autofree char *display_session_type = NULL;
- if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED)
+ if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
+ g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
return;
+ }
g_object_get (G_OBJECT (display),
"session-type", &display_session_type,
NULL);
/* we can only stop greeter for wayland sessions, since
* X server would jump back on exit */
- if (g_strcmp0 (display_session_type, "wayland") != 0)
+ if (g_strcmp0 (display_session_type, "wayland") != 0) {
+ g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
return;
+ }
+ g_debug ("GdmLocalDisplayFactory: killing login window since its now unused");
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
}
static gboolean
on_vt_changed (GIOChannel *source,
GIOCondition condition,
GdmLocalDisplayFactory *factory)
{
GIOStatus status;
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
g_autofree char *tty_of_previous_vt = NULL;
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
g_autofree char *active_session_id = NULL;
const char *session_type = NULL;
int ret;
+ g_debug ("GdmLocalDisplayFactory: received VT change event");
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
if (condition & G_IO_PRI) {
g_autoptr (GError) error = NULL;
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
if (error != NULL) {
g_warning ("could not read active VT from kernel: %s", error->message);
}
switch (status) {
case G_IO_STATUS_ERROR:
return G_SOURCE_REMOVE;
case G_IO_STATUS_EOF:
return G_SOURCE_REMOVE;
case G_IO_STATUS_AGAIN:
return G_SOURCE_CONTINUE;
case G_IO_STATUS_NORMAL:
break;
}
}
- if ((condition & G_IO_ERR) || (condition & G_IO_HUP))
+ if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
+ g_debug ("GdmLocalDisplayFactory: kernel hung up active vt watch");
return G_SOURCE_REMOVE;
+ }
- if (tty_of_active_vt == NULL)
+ if (tty_of_active_vt == NULL) {
+ g_debug ("GdmLocalDisplayFactory: unable to read active VT from kernel");
return G_SOURCE_CONTINUE;
+ }
g_strchomp (tty_of_active_vt);
- /* don't do anything if we're on the same VT we were before */
- if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0)
- return G_SOURCE_CONTINUE;
-
tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
+ /* don't do anything at start up */
+ if (tty_of_previous_vt == NULL) {
+ g_debug ("GdmLocalDisplayFactory: VT is %s at startup",
+ factory->priv->tty_of_active_vt);
+ return G_SOURCE_CONTINUE;
+ }
+
+ g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
+ tty_of_previous_vt, factory->priv->tty_of_active_vt);
+
/* if the old VT was running a wayland login screen kill it
*/
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
unsigned int vt;
ret = sd_session_get_vt (login_session_id, &vt);
if (ret == 0 && vt != 0) {
g_autofree char *tty_of_login_window_vt = NULL;
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
+ g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
GdmDisplayStore *store;
GdmDisplay *display;
+ g_debug ("GdmLocalDisplayFactory: VT switched from login window");
+
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL)
maybe_stop_greeter_display (display);
+ } else {
+ g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
}
}
}
/* if user jumped back to initial vt and it's empty put a login screen
* on it (unless a login screen is already running elsewhere, then
* jump to that login screen)
*/
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
+ g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
if (ret == 0) {
g_autofree char *state = NULL;
ret = sd_session_get_state (active_session_id, &state);
/* if there's something already running on the active VT then bail */
- if (ret == 0 && g_strcmp0 (state, "closing") != 0)
+ if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
+ g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
return G_SOURCE_CONTINUE;
+ }
}
if (gdm_local_display_factory_use_wayland ())
session_type = "wayland";
+ g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
+
create_display (factory, "seat0", session_type, TRUE);
return G_SOURCE_CONTINUE;
}
#endif
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatNew",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_new,
g_object_ref (factory),
g_object_unref);
factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatRemoved",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_removed,
g_object_ref (factory),
--
2.27.0

View File

@ -1,97 +0,0 @@
From e5bf6d78ff8f54bbb74e572f05ccbf1c0df24017 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Aug 2018 13:55:06 -0400
Subject: [PATCH 16/51] local-display-factory: don't start two greeters at
startup
commit c0188a7030 added some complex code for starting
the login screen when the user switches to the initial
VT if nothing is running on that VT.
The problem is, we get a VT change event on that VT as
part of the start up process.
This leads to an additional greeter getting started.
This commit adds a check to side step the new code during
startup.
Closes: https://gitlab.gnome.org/GNOME/gdm/issues/409
---
daemon/gdm-local-display-factory.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 2a2259f2a..9f377ba9a 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -600,60 +600,66 @@ on_vt_changed (GIOChannel *source,
g_autoptr (GError) error = NULL;
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
if (error != NULL) {
g_warning ("could not read active VT from kernel: %s", error->message);
}
switch (status) {
case G_IO_STATUS_ERROR:
return G_SOURCE_REMOVE;
case G_IO_STATUS_EOF:
return G_SOURCE_REMOVE;
case G_IO_STATUS_AGAIN:
return G_SOURCE_CONTINUE;
case G_IO_STATUS_NORMAL:
break;
}
}
if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
g_debug ("GdmLocalDisplayFactory: kernel hung up active vt watch");
return G_SOURCE_REMOVE;
}
if (tty_of_active_vt == NULL) {
g_debug ("GdmLocalDisplayFactory: unable to read active VT from kernel");
return G_SOURCE_CONTINUE;
}
g_strchomp (tty_of_active_vt);
+ /* don't do anything if we're on the same VT we were before */
+ if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0) {
+ g_debug ("GdmLocalDisplayFactory: VT changed to the same VT, ignoring");
+ return G_SOURCE_CONTINUE;
+ }
+
tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
/* don't do anything at start up */
if (tty_of_previous_vt == NULL) {
g_debug ("GdmLocalDisplayFactory: VT is %s at startup",
factory->priv->tty_of_active_vt);
return G_SOURCE_CONTINUE;
}
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
tty_of_previous_vt, factory->priv->tty_of_active_vt);
/* if the old VT was running a wayland login screen kill it
*/
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
unsigned int vt;
ret = sd_session_get_vt (login_session_id, &vt);
if (ret == 0 && vt != 0) {
g_autofree char *tty_of_login_window_vt = NULL;
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
GdmDisplayStore *store;
GdmDisplay *display;
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
--
2.27.0

View File

@ -1,128 +0,0 @@
From de4b24f63e62a39b2cb10a8c58c54d86559f7f26 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Aug 2018 14:04:44 -0400
Subject: [PATCH 17/51] session-worker: don't switch VTs if we're already on
the right VT
commit 5b5dccbd shows that switching VTs to the same VT isn't
exactly a no-op. In order to prevent unnecessary wakeups, avoid
switching VTs if the worker is already on the correct VT.
---
daemon/gdm-session-worker.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 0322037e0..fd6470bab 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -936,91 +936,101 @@ fix_terminal_vt_mode (GdmSessionWorker *worker,
if (ioctl (tty_fd, KDGETMODE, &kernel_display_mode) < 0) {
g_debug ("GdmSessionWorker: couldn't query kernel display mode: %m");
succeeded = FALSE;
}
if (kernel_display_mode == KD_TEXT) {
goto out;
}
/* VT is in the anti-social state of VT_AUTO + KD_GRAPHICS,
* fix it.
*/
succeeded = handle_terminal_vt_switches (worker, tty_fd);
mode_fixed = TRUE;
out:
if (!succeeded) {
g_error ("GdmSessionWorker: couldn't set up terminal, aborting...");
return;
}
g_debug ("GdmSessionWorker: VT mode did %sneed to be fixed",
mode_fixed? "" : "not ");
}
static void
jump_to_vt (GdmSessionWorker *worker,
int vt_number)
{
int fd;
int active_vt_tty_fd;
+ int active_vt = -1;
+ struct vt_stat vt_state = { 0 };
g_debug ("GdmSessionWorker: jumping to VT %d", vt_number);
active_vt_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
if (worker->priv->session_tty_fd != -1) {
fd = worker->priv->session_tty_fd;
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
}
/* It's possible that the current VT was left in a broken
* combination of states (KD_GRAPHICS with VT_AUTO), that
* can't be switched away from. This call makes sure things
* are set in a way that VT_ACTIVATE should work and
* VT_WAITACTIVE shouldn't hang.
*/
fix_terminal_vt_mode (worker, active_vt_tty_fd);
} else {
fd = active_vt_tty_fd;
}
handle_terminal_vt_switches (worker, fd);
- if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
- g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
- vt_number);
- } else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
- g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
- vt_number);
+ if (ioctl (fd, VT_GETSTATE, &vt_state) <= 0) {
+ g_debug ("GdmSessionWorker: couldn't get current VT: %m");
+ } else {
+ active_vt = vt_state.v_active;
+ }
+
+ if (active_vt != vt_number) {
+ if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
+ g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
+ vt_number);
+ } else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
+ g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
+ vt_number);
+ }
}
close (active_vt_tty_fd);
}
static void
gdm_session_worker_set_state (GdmSessionWorker *worker,
GdmSessionWorkerState state)
{
if (worker->priv->state == state)
return;
worker->priv->state = state;
g_object_notify (G_OBJECT (worker), "state");
}
static void
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
int status)
{
g_debug ("GdmSessionWorker: uninitializing PAM");
if (worker->priv->pam_handle == NULL)
return;
gdm_session_worker_get_username (worker, NULL);
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
pam_close_session (worker->priv->pam_handle, 0);
gdm_session_auditor_report_logout (worker->priv->auditor);
--
2.27.0

View File

@ -1,87 +0,0 @@
From b9e5a2879a410b6a85be6c01c6f49cd7eb24c800 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 31 Aug 2018 15:20:39 -0400
Subject: [PATCH 18/51] session-worker: fix current vt detection short-circuit
logic
commit 8169cd4 attempts to avoid changing VTs if the active VT
is the same as the VT getting jumped to.
It fails to work, however, because accidentally treats a 0 return
code to the VT_GETSTATE ioctl as failure.
this commit fixes that.
---
daemon/gdm-session-worker.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index fd6470bab..391969d96 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -963,61 +963,61 @@ jump_to_vt (GdmSessionWorker *worker,
{
int fd;
int active_vt_tty_fd;
int active_vt = -1;
struct vt_stat vt_state = { 0 };
g_debug ("GdmSessionWorker: jumping to VT %d", vt_number);
active_vt_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
if (worker->priv->session_tty_fd != -1) {
fd = worker->priv->session_tty_fd;
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
}
/* It's possible that the current VT was left in a broken
* combination of states (KD_GRAPHICS with VT_AUTO), that
* can't be switched away from. This call makes sure things
* are set in a way that VT_ACTIVATE should work and
* VT_WAITACTIVE shouldn't hang.
*/
fix_terminal_vt_mode (worker, active_vt_tty_fd);
} else {
fd = active_vt_tty_fd;
}
handle_terminal_vt_switches (worker, fd);
- if (ioctl (fd, VT_GETSTATE, &vt_state) <= 0) {
+ if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
g_debug ("GdmSessionWorker: couldn't get current VT: %m");
} else {
active_vt = vt_state.v_active;
}
if (active_vt != vt_number) {
if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
vt_number);
} else if (ioctl (fd, VT_WAITACTIVE, vt_number) < 0) {
g_debug ("GdmSessionWorker: couldn't finalize jump to VT %d: %m",
vt_number);
}
}
close (active_vt_tty_fd);
}
static void
gdm_session_worker_set_state (GdmSessionWorker *worker,
GdmSessionWorkerState state)
{
if (worker->priv->state == state)
return;
worker->priv->state = state;
g_object_notify (G_OBJECT (worker), "state");
}
static void
--
2.27.0

View File

@ -1,168 +0,0 @@
From fe680d77cff9272843cb171c7e590c239f7afe5a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 9 Aug 2018 12:32:31 -0400
Subject: [PATCH 19/51] local-display-factory: don't jump to failed display
Since commit 5e737a57 `create_display` will jump to any
already running login screen if it can find one.
Right now if a display fails we call `create_display` to
create a new one. It will look for any already running
login screen and find the recently failed display.
This commit make sure we never jump to a display that isn't
in good working order.
---
daemon/gdm-local-display-factory.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 9f377ba9a..c58de9c17 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -60,60 +60,63 @@ struct GdmLocalDisplayFactoryPrivate
guint num_failures;
guint seat_new_id;
guint seat_removed_id;
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
char *tty_of_active_vt;
guint active_vt_watch_id;
#endif
};
enum {
PROP_0,
};
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
static void gdm_local_display_factory_finalize (GObject *object);
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial_display);
static void on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory);
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
static gpointer local_display_factory_object = NULL;
+static gboolean lookup_by_session_id (const char *id,
+ GdmDisplay *display,
+ gpointer user_data);
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
GQuark
gdm_local_display_factory_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_local_display_factory_error");
}
return ret;
}
static void
listify_hash (gpointer key,
GdmDisplay *display,
GList **list)
{
*list = g_list_prepend (*list, key);
}
static int
sort_nums (gpointer a,
gpointer b)
{
guint32 num_a;
guint32 num_b;
num_a = GPOINTER_TO_UINT (a);
@@ -370,66 +373,74 @@ lookup_by_seat_id (const char *id,
g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
static GdmDisplay *
create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
char *active_session_id = NULL;
int ret;
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
if (ret == 0) {
char *login_session_id = NULL;
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
- if (g_strcmp0 (active_session_id, login_session_id) != 0) {
- gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
+ GdmDisplay *display;
+
+ display = gdm_display_store_find (store,
+ lookup_by_session_id,
+ (gpointer) login_session_id);
+ if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
+ if (g_strcmp0 (active_session_id, login_session_id) != 0) {
+ gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
+ }
+ g_clear_pointer (&login_session_id, g_free);
+ g_clear_pointer (&active_session_id, g_free);
+ return NULL;
}
g_clear_pointer (&login_session_id, g_free);
- g_clear_pointer (&active_session_id, g_free);
- return NULL;
}
g_clear_pointer (&active_session_id, g_free);
} else if (!sd_seat_can_multi_session (seat_id)) {
/* Ensure we don't create the same display more than once */
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
if (display != NULL) {
return NULL;
}
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
--
2.27.0

View File

@ -1,161 +0,0 @@
From 94207dd5699f1cd2fe7d516c20e1de2b2e2778fb Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 9 Aug 2018 12:48:25 -0400
Subject: [PATCH 20/51] local-display-factory: add some more debug statements
This commit just sprinkles in a few more `g_debug`'s for
log file clarity.
---
daemon/gdm-local-display-factory.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index c58de9c17..6f3a4c391 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -364,76 +364,80 @@ on_display_status_changed (GdmDisplay *display,
static gboolean
lookup_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
static GdmDisplay *
create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
char *active_session_id = NULL;
int ret;
+ g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
+ session_type? : "X11", seat_id);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
if (ret == 0) {
char *login_session_id = NULL;
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
GdmDisplay *display;
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
if (g_strcmp0 (active_session_id, login_session_id) != 0) {
+ g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
+ login_session_id);
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
}
g_clear_pointer (&login_session_id, g_free);
g_clear_pointer (&active_session_id, g_free);
return NULL;
}
g_clear_pointer (&login_session_id, g_free);
}
g_clear_pointer (&active_session_id, g_free);
} else if (!sd_seat_can_multi_session (seat_id)) {
/* Ensure we don't create the same display more than once */
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
if (display != NULL) {
return NULL;
}
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
@@ -453,60 +457,61 @@ create_display (GdmLocalDisplayFactory *factory,
g_object_unref (display);
if (! gdm_display_manage (display)) {
gdm_display_unmanage (display);
}
return display;
}
static void
delete_display (GdmLocalDisplayFactory *factory,
const char *seat_id) {
GdmDisplayStore *store;
g_debug ("GdmLocalDisplayFactory: Removing used_display_numbers on seat %s", seat_id);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id);
}
static gboolean
gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
{
GError *error = NULL;
GVariant *result;
GVariant *array;
GVariantIter iter;
const char *seat;
+ g_debug ("GdmLocalDisplayFactory: enumerating seats from logind");
result = g_dbus_connection_call_sync (factory->priv->connection,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"ListSeats",
NULL,
G_VARIANT_TYPE ("(a(so))"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, &error);
if (!result) {
g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error->message);
g_clear_error (&error);
return FALSE;
}
array = g_variant_get_child_value (result, 0);
g_variant_iter_init (&iter, array);
while (g_variant_iter_loop (&iter, "(&so)", &seat, NULL)) {
gboolean is_initial;
const char *session_type = NULL;
if (g_strcmp0 (seat, "seat0") == 0) {
is_initial = TRUE;
if (gdm_local_display_factory_use_wayland ())
session_type = "wayland";
} else {
is_initial = FALSE;
--
2.27.0

View File

@ -1,162 +0,0 @@
From abd8e1ef71d093a3ab5c110aea5fa2012d59d5e2 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 14 Aug 2018 10:21:17 -0400
Subject: [PATCH 21/51] local-display-factory: ignore spurios SeatNew signal at
start up
Sometimes during startup, logind will send a `SeatNew` signal for
seat0 after GDM has already called `ListSeats` and processed `seat0`.
That `SeatNew` signal leads to GDM calling `create_display` twice in
quick succession.
This commit changes GDM to avoid such double processing, by ignoring
the `create_display` requests for seats that already have a prepared
display ("prepared" means "starting up").
Closes: https://gitlab.gnome.org/GNOME/gdm/issues/410
---
daemon/gdm-local-display-factory.c | 33 +++++++++++++++++++++++-------
1 file changed, 26 insertions(+), 7 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 6f3a4c391..127127005 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -353,107 +353,126 @@ on_display_status_changed (GdmDisplay *display,
case GDM_DISPLAY_MANAGED:
break;
default:
g_assert_not_reached ();
break;
}
g_free (seat_id);
g_free (session_type);
g_free (session_class);
}
static gboolean
lookup_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &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);
+}
+
static GdmDisplay *
create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
char *active_session_id = NULL;
int ret;
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
session_type? : "X11", seat_id);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+ if (sd_seat_can_multi_session (seat_id))
+ display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
+ else
+ display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
+
+ /* Ensure we don't create the same display more than once */
+ if (display != NULL) {
+ g_debug ("GdmLocalDisplayFactory: display already created");
+ return NULL;
+ }
+
ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
if (ret == 0) {
char *login_session_id = NULL;
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
GdmDisplay *display;
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
if (g_strcmp0 (active_session_id, login_session_id) != 0) {
g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
login_session_id);
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
}
g_clear_pointer (&login_session_id, g_free);
g_clear_pointer (&active_session_id, g_free);
return NULL;
}
g_clear_pointer (&login_session_id, g_free);
}
g_clear_pointer (&active_session_id, g_free);
- } else if (!sd_seat_can_multi_session (seat_id)) {
- /* Ensure we don't create the same display more than once */
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
-
- if (display != NULL) {
- return NULL;
- }
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
g_object_set (display, "seat-id", seat_id, NULL);
g_object_set (display, "is-initial", initial, NULL);
store_display (factory, display);
/* let store own the ref */
g_object_unref (display);
if (! gdm_display_manage (display)) {
--
2.27.0

View File

@ -1,91 +0,0 @@
From 9b8c21080286f943d0a19431bc8c0061f4833443 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 30 Aug 2018 13:04:56 -0400
Subject: [PATCH 22/51] common: remove unnecessary free
This commit drops an erroneous free call, that would
potentially free a dangling pointer.
Luckily the error condition can never occur because the
error code checked is never returned, so the free call
is dead code.
This commit removes the free call. A subsequent commit
will fix the error code checking.
---
common/gdm-common.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/common/gdm-common.c b/common/gdm-common.c
index 59317a889..c909aceee 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -391,64 +391,62 @@ gdm_activate_session_by_id (GDBusConnection *connection,
return TRUE;
}
gboolean
gdm_get_login_window_session_id (const char *seat_id,
char **session_id)
{
gboolean ret;
int res, i;
char **sessions;
char *service_id;
char *service_class;
char *state;
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
if (res < 0) {
g_debug ("Failed to determine sessions: %s", strerror (-res));
return FALSE;
}
if (sessions == NULL || sessions[0] == NULL) {
*session_id = NULL;
ret = FALSE;
goto out;
}
for (i = 0; sessions[i]; i ++) {
res = sd_session_get_class (sessions[i], &service_class);
if (res < 0) {
- if (res == -ENOENT) {
- free (service_class);
+ if (res == -ENOENT)
continue;
- }
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_class, "greeter") != 0) {
free (service_class);
continue;
}
free (service_class);
ret = sd_session_get_state (sessions[i], &state);
if (ret < 0) {
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (g_strcmp0 (state, "closing") == 0) {
free (state);
continue;
}
free (state);
res = sd_session_get_service (sessions[i], &service_id);
if (res < 0) {
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
--
2.27.0

View File

@ -1,133 +0,0 @@
From 4a948e4b203fdf5fcd9b5e53dd4a80ef2786c0cd Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 30 Aug 2018 13:06:54 -0400
Subject: [PATCH 23/51] common: don't bail if session disappears out from under
us
It's entirely possible for a session returned by
sd_seat_get_sessions to disappear immediately after the
sd_seat_get_sessions call returns. This is especially
likely at logout time where the session will briefly be
in the "closing" state before getting reaped.
If that happens when we're looking for a greeter session, we
stop looking for a greeter session and bail out all confused.
This commit fixes the confusion by gracefully handling the
session disappearing by just proceeding to the next session
in the list.
This commit is very similar to commit 155ee7eca which got
accidentally reverted during code consolidation. The main
difference is this commit checks the correct error code
of -ENXIO instead of -ENOENT, so it might actually fix
what it's ostensibly supposed to fix.
---
common/gdm-common.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/common/gdm-common.c b/common/gdm-common.c
index c909aceee..59b8dfc44 100644
--- a/common/gdm-common.c
+++ b/common/gdm-common.c
@@ -391,90 +391,96 @@ gdm_activate_session_by_id (GDBusConnection *connection,
return TRUE;
}
gboolean
gdm_get_login_window_session_id (const char *seat_id,
char **session_id)
{
gboolean ret;
int res, i;
char **sessions;
char *service_id;
char *service_class;
char *state;
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
if (res < 0) {
g_debug ("Failed to determine sessions: %s", strerror (-res));
return FALSE;
}
if (sessions == NULL || sessions[0] == NULL) {
*session_id = NULL;
ret = FALSE;
goto out;
}
for (i = 0; sessions[i]; i ++) {
res = sd_session_get_class (sessions[i], &service_class);
if (res < 0) {
- if (res == -ENOENT)
+ if (res == -ENXIO)
continue;
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_class, "greeter") != 0) {
free (service_class);
continue;
}
free (service_class);
ret = sd_session_get_state (sessions[i], &state);
if (ret < 0) {
+ if (res == -ENXIO)
+ continue;
+
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (g_strcmp0 (state, "closing") == 0) {
free (state);
continue;
}
free (state);
res = sd_session_get_service (sessions[i], &service_id);
if (res < 0) {
+ if (res == -ENXIO)
+ continue;
+
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
ret = FALSE;
goto out;
}
if (strcmp (service_id, "gdm-launch-environment") == 0) {
*session_id = g_strdup (sessions[i]);
ret = TRUE;
free (service_id);
goto out;
}
free (service_id);
}
*session_id = NULL;
ret = FALSE;
out:
if (sessions) {
for (i = 0; sessions[i]; i ++) {
free (sessions[i]);
}
free (sessions);
}
return ret;
}
--
2.27.0

View File

@ -1,138 +0,0 @@
From fac23cfa3e8e9fe21563733c0c1b739ddecead8a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 30 Aug 2018 14:01:55 -0400
Subject: [PATCH 24/51] manager: better logind handling
commit 9ee68d5c8 highlights we've incorrectly
used ENOENT instead of ENXIO when checking for
non-existing sessions/seats with logind.
This commit mops up all the other cases.
---
daemon/gdm-manager.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 80f60d24c..367a731cc 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -361,113 +361,113 @@ find_session_for_user_on_seat (GdmManager *manager,
candidate_username);
if (g_strcmp0 (candidate_username, username) == 0 &&
g_strcmp0 (candidate_seat_id, seat_id) == 0) {
g_debug ("GdmManager: yes, found session %s", candidate_session_id);
return candidate_session;
}
g_debug ("GdmManager: no, will not use session %s", candidate_session_id);
}
g_debug ("GdmManager: no matching sessions found");
return NULL;
}
static gboolean
is_remote_session (GdmManager *self,
const char *session_id,
GError **error)
{
char *seat;
int ret;
gboolean is_remote;
/* FIXME: The next release of logind is going to have explicit api for
* checking remoteness.
*/
seat = NULL;
ret = sd_session_get_seat (session_id, &seat);
- if (ret < 0 && ret != -ENOENT) {
+ if (ret < 0 && ret != -ENXIO) {
g_debug ("GdmManager: Error while retrieving seat for session %s: %s",
session_id, strerror (-ret));
}
if (seat != NULL) {
is_remote = FALSE;
free (seat);
} else {
is_remote = TRUE;
}
return is_remote;
}
static char *
get_seat_id_for_session_id (const char *session_id,
GError **error)
{
int ret;
char *seat, *out_seat;
seat = NULL;
ret = sd_session_get_seat (session_id, &seat);
- if (ret == -ENOENT) {
+ if (ret == -ENXIO) {
out_seat = NULL;
} else if (ret < 0) {
g_set_error (error,
GDM_DISPLAY_ERROR,
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
"Error getting uid for session id %s from systemd: %s",
session_id,
g_strerror (-ret));
out_seat = NULL;
} else {
out_seat = g_strdup (seat);
free (seat);
}
return out_seat;
}
static char *
get_tty_for_session_id (const char *session_id,
GError **error)
{
int ret;
char *tty, *out_tty;
ret = sd_session_get_tty (session_id, &tty);
- if (ret == -ENOENT) {
+ if (ret == -ENXIO) {
out_tty = NULL;
} else if (ret < 0) {
g_set_error (error,
GDM_DISPLAY_ERROR,
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
"Error getting tty for session id %s from systemd: %s",
session_id,
g_strerror (-ret));
out_tty = NULL;
} else {
out_tty = g_strdup (tty);
free (tty);
}
return out_tty;
}
static void
get_display_and_details_for_bus_sender (GdmManager *self,
GDBusConnection *connection,
const char *sender,
GdmDisplay **out_display,
char **out_seat_id,
char **out_session_id,
char **out_tty,
GPid *out_pid,
uid_t *out_uid,
gboolean *out_is_login_screen,
gboolean *out_is_remote)
{
--
2.27.0

View File

@ -1,90 +0,0 @@
From cabcd21c17ca98e517a3eea7c9d5ce269445e3e0 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 31 Aug 2018 15:46:55 -0400
Subject: [PATCH 25/51] session-worker: clear VT before jumping to it
If we're going to jump to a new VT we should make sure it's free
of residual console text. That way if there's flicker the user
will be less likely to notice it.
This commit sends a clear screen escape sequence to the tty
before jumping to it.
---
daemon/gdm-session-worker.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 391969d96..7ed2789da 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -943,60 +943,67 @@ fix_terminal_vt_mode (GdmSessionWorker *worker,
}
/* VT is in the anti-social state of VT_AUTO + KD_GRAPHICS,
* fix it.
*/
succeeded = handle_terminal_vt_switches (worker, tty_fd);
mode_fixed = TRUE;
out:
if (!succeeded) {
g_error ("GdmSessionWorker: couldn't set up terminal, aborting...");
return;
}
g_debug ("GdmSessionWorker: VT mode did %sneed to be fixed",
mode_fixed? "" : "not ");
}
static void
jump_to_vt (GdmSessionWorker *worker,
int vt_number)
{
int fd;
int active_vt_tty_fd;
int active_vt = -1;
struct vt_stat vt_state = { 0 };
g_debug ("GdmSessionWorker: jumping to VT %d", vt_number);
active_vt_tty_fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
if (worker->priv->session_tty_fd != -1) {
+ static const char *clear_screen_escape_sequence = "\33[H\33[2J";
+
+ /* let's make sure the new VT is clear */
+ write (worker->priv->session_tty_fd,
+ clear_screen_escape_sequence,
+ sizeof (clear_screen_escape_sequence));
+
fd = worker->priv->session_tty_fd;
g_debug ("GdmSessionWorker: first setting graphics mode to prevent flicker");
if (ioctl (fd, KDSETMODE, KD_GRAPHICS) < 0) {
g_debug ("GdmSessionWorker: couldn't set graphics mode: %m");
}
/* It's possible that the current VT was left in a broken
* combination of states (KD_GRAPHICS with VT_AUTO), that
* can't be switched away from. This call makes sure things
* are set in a way that VT_ACTIVATE should work and
* VT_WAITACTIVE shouldn't hang.
*/
fix_terminal_vt_mode (worker, active_vt_tty_fd);
} else {
fd = active_vt_tty_fd;
}
handle_terminal_vt_switches (worker, fd);
if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
g_debug ("GdmSessionWorker: couldn't get current VT: %m");
} else {
active_vt = vt_state.v_active;
}
if (active_vt != vt_number) {
if (ioctl (fd, VT_ACTIVATE, vt_number) < 0) {
g_debug ("GdmSessionWorker: couldn't initiate jump to VT %d: %m",
vt_number);
--
2.27.0

View File

@ -1,133 +0,0 @@
From b773eb570d8c5f9d2222ee39eecbc6a622d108d8 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 30 Aug 2018 16:04:41 -0400
Subject: [PATCH 26/51] manager: don't set ran_once after running initial-setup
GdmManager tracks whether or not the user session has ran
once, so it won't autologin a user again after logout.
Unfortunately the initial-setup session was counting toward the
ran_once count preventing initial-setup from logging the user
in afterward.
This commit prevents ran_once from getting set in that case.
---
daemon/gdm-manager.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 367a731cc..c8197a043 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1519,105 +1519,107 @@ set_up_session (GdmManager *manager,
operation->username = username;
g_signal_connect (user,
"notify::is-loaded",
G_CALLBACK (on_user_is_loaded_changed),
operation);
}
}
static void
greeter_display_started (GdmManager *manager,
GdmDisplay *display)
{
if (manager->priv->ran_once) {
return;
}
maybe_start_pending_initial_login (manager, display);
}
static void
on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmManager *manager)
{
int status;
int display_number = -1;
char *session_type = NULL;
#ifdef WITH_PLYMOUTH
gboolean display_is_local = FALSE;
+ gboolean doing_initial_setup = FALSE;
gboolean quit_plymouth = FALSE;
g_object_get (display,
"is-local", &display_is_local,
+ "doing-initial-setup", &doing_initial_setup,
NULL);
quit_plymouth = display_is_local && manager->priv->plymouth_is_running;
#endif
g_object_get (display,
"x11-display-number", &display_number,
"session-type", &session_type,
NULL);
status = gdm_display_get_status (display);
switch (status) {
case GDM_DISPLAY_PREPARED:
case GDM_DISPLAY_MANAGED:
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
char *session_class;
g_object_get (display,
"session-class", &session_class,
NULL);
if (g_strcmp0 (session_class, "greeter") == 0)
set_up_session (manager, display);
g_free (session_class);
}
if (status == GDM_DISPLAY_MANAGED) {
greeter_display_started (manager, display);
}
break;
case GDM_DISPLAY_FAILED:
case GDM_DISPLAY_UNMANAGED:
case GDM_DISPLAY_FINISHED:
#ifdef WITH_PLYMOUTH
if (quit_plymouth) {
plymouth_quit_without_transition ();
manager->priv->plymouth_is_running = FALSE;
}
#endif
- if (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0) {
+ if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
manager->priv->ran_once = TRUE;
}
maybe_start_pending_initial_login (manager, display);
break;
default:
break;
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmManager *manager)
{
char *id;
gdm_display_get_id (display, &id, NULL);
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
g_free (id);
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
}
static void
destroy_start_user_session_operation (StartUserSessionOperation *operation)
{
g_object_set_data (G_OBJECT (operation->session),
--
2.27.0

View File

@ -1,418 +0,0 @@
From 3d4199f82136e7046b5b08fc7c583e3fce2d04a2 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 31 Aug 2018 14:33:58 -0400
Subject: [PATCH 27/51] manager: start initial setup right away
We no longer restart the greeter as soon as it dies, since we
start the greeter on demand. This means, we no longer need to
defer starting initial setup until after the greeter respawns.
Furthermore, it doesn't work anymore since it relied on the
respawn to trigger.
This commit removes that code and scaffolding and just starts
initial setup directly.
https://gitlab.gnome.org/GNOME/gdm/issues/415
---
daemon/gdm-manager.c | 66 +-------------------------------------------
1 file changed, 1 insertion(+), 65 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index c8197a043..fb7b1ec4b 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -62,62 +62,60 @@
#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
typedef struct
{
GdmManager *manager;
GdmSession *session;
char *service_name;
guint idle_id;
} StartUserSessionOperation;
struct GdmManagerPrivate
{
GdmDisplayStore *display_store;
GdmLocalDisplayFactory *local_factory;
#ifdef HAVE_LIBXDMCP
GdmXdmcpDisplayFactory *xdmcp_factory;
#endif
GList *user_sessions;
GHashTable *transient_sessions;
GHashTable *open_reauthentication_requests;
gboolean xdmcp_enabled;
gboolean started;
gboolean show_local_greeter;
GDBusConnection *connection;
GDBusObjectManagerServer *object_manager;
- StartUserSessionOperation *initial_login_operation;
-
#ifdef WITH_PLYMOUTH
guint plymouth_is_running : 1;
#endif
guint ran_once : 1;
};
enum {
PROP_0,
PROP_XDMCP_ENABLED,
PROP_SHOW_LOCAL_GREETER
};
enum {
DISPLAY_ADDED,
DISPLAY_REMOVED,
LAST_SIGNAL
};
typedef enum {
SESSION_RECORD_LOGIN,
SESSION_RECORD_LOGOUT,
SESSION_RECORD_FAILED,
} SessionRecord;
static guint signals [LAST_SIGNAL] = { 0, };
static void gdm_manager_class_init (GdmManagerClass *klass);
static void gdm_manager_init (GdmManager *manager);
static void gdm_manager_dispose (GObject *object);
@@ -1286,96 +1284,60 @@ get_automatic_login_details (GdmManager *manager,
if (res && enabled) {
res = gdm_settings_direct_get_string (GDM_KEY_AUTO_LOGIN_USER, &username);
}
if (enabled && res && username != NULL && username[0] != '\0') {
goto out;
}
g_free (username);
username = NULL;
enabled = FALSE;
out:
if (enabled) {
g_debug ("GdmDisplay: Got automatic login details for display: %d %s",
enabled,
username);
} else {
g_debug ("GdmDisplay: Got automatic login details for display: 0");
}
if (usernamep != NULL) {
*usernamep = username;
} else {
g_free (username);
}
return enabled;
}
-static void
-maybe_start_pending_initial_login (GdmManager *manager,
- GdmDisplay *greeter_display)
-{
- StartUserSessionOperation *operation;
- char *greeter_seat_id = NULL;
- char *user_session_seat_id = NULL;
-
- /* There may be a user session waiting to be started.
- * This would happen if we couldn't start it earlier because
- * the login screen X server was coming up and two X servers
- * can't be started on the same seat at the same time.
- */
-
- if (manager->priv->initial_login_operation == NULL) {
- return;
- }
-
- operation = manager->priv->initial_login_operation;
-
- g_object_get (G_OBJECT (greeter_display),
- "seat-id", &greeter_seat_id,
- NULL);
- g_object_get (G_OBJECT (operation->session),
- "display-seat-id", &user_session_seat_id,
- NULL);
-
- if (g_strcmp0 (greeter_seat_id, user_session_seat_id) == 0) {
- start_user_session (manager, operation);
- manager->priv->initial_login_operation = NULL;
- }
-
- g_free (greeter_seat_id);
- g_free (user_session_seat_id);
-}
-
static const char *
get_username_for_greeter_display (GdmManager *manager,
GdmDisplay *display)
{
gboolean doing_initial_setup = FALSE;
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
NULL);
if (doing_initial_setup) {
return INITIAL_SETUP_USERNAME;
} else {
return GDM_USERNAME;
}
}
static void
set_up_automatic_login_session (GdmManager *manager,
GdmDisplay *display)
{
GdmSession *session;
char *display_session_type = NULL;
gboolean is_initial;
/* 0 is root user; since the daemon talks to the session object
* directly, itself, for automatic login
*/
session = create_user_session_for_display (manager, display, 0);
@@ -1498,131 +1460,115 @@ set_up_session (GdmManager *manager,
return;
}
#endif
set_up_greeter_session (manager, display);
return;
}
/* Check whether the user really exists before committing to autologin. */
user_manager = act_user_manager_get_default ();
user = act_user_manager_get_user (user_manager, username);
g_object_get (user_manager, "is-loaded", &loaded, NULL);
if (loaded) {
set_up_automatic_login_session_if_user_exists (manager, display, user);
} else {
UsernameLookupOperation *operation;
operation = g_new (UsernameLookupOperation, 1);
operation->manager = g_object_ref (manager);
operation->display = g_object_ref (display);
operation->username = username;
g_signal_connect (user,
"notify::is-loaded",
G_CALLBACK (on_user_is_loaded_changed),
operation);
}
}
-static void
-greeter_display_started (GdmManager *manager,
- GdmDisplay *display)
-{
- if (manager->priv->ran_once) {
- return;
- }
-
- maybe_start_pending_initial_login (manager, display);
-}
-
static void
on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmManager *manager)
{
int status;
int display_number = -1;
char *session_type = NULL;
#ifdef WITH_PLYMOUTH
gboolean display_is_local = FALSE;
gboolean doing_initial_setup = FALSE;
gboolean quit_plymouth = FALSE;
g_object_get (display,
"is-local", &display_is_local,
"doing-initial-setup", &doing_initial_setup,
NULL);
quit_plymouth = display_is_local && manager->priv->plymouth_is_running;
#endif
g_object_get (display,
"x11-display-number", &display_number,
"session-type", &session_type,
NULL);
status = gdm_display_get_status (display);
switch (status) {
case GDM_DISPLAY_PREPARED:
case GDM_DISPLAY_MANAGED:
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
char *session_class;
g_object_get (display,
"session-class", &session_class,
NULL);
if (g_strcmp0 (session_class, "greeter") == 0)
set_up_session (manager, display);
g_free (session_class);
}
-
- if (status == GDM_DISPLAY_MANAGED) {
- greeter_display_started (manager, display);
- }
break;
case GDM_DISPLAY_FAILED:
case GDM_DISPLAY_UNMANAGED:
case GDM_DISPLAY_FINISHED:
#ifdef WITH_PLYMOUTH
if (quit_plymouth) {
plymouth_quit_without_transition ();
manager->priv->plymouth_is_running = FALSE;
}
#endif
if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
manager->priv->ran_once = TRUE;
}
- maybe_start_pending_initial_login (manager, display);
break;
default:
break;
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmManager *manager)
{
char *id;
gdm_display_get_id (display, &id, NULL);
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
g_free (id);
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
}
static void
destroy_start_user_session_operation (StartUserSessionOperation *operation)
{
g_object_set_data (G_OBJECT (operation->session),
"start-user-session-operation",
NULL);
g_object_unref (operation->session);
@@ -1723,97 +1669,87 @@ on_start_user_session (StartUserSessionOperation *operation)
gdm_session_reset (operation->session);
destroy_start_user_session_operation (operation);
goto out;
}
display = get_display_for_user_session (operation->session);
g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
session_id = gdm_session_get_conversation_session_id (operation->session,
operation->service_name);
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
/* In this case, the greeter's display is morphing into
* the user session display. Kill the greeter on this session
* and let the user session follow the same display. */
gdm_display_stop_greeter_session (display);
g_object_set (G_OBJECT (display),
"session-class", "user",
"session-id", session_id,
NULL);
} else {
uid_t allowed_uid;
g_object_ref (display);
if (doing_initial_setup) {
g_debug ("GdmManager: closing down initial setup display");
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
-
- /* We can't start the user session until the finished display
- * starts to respawn (since starting an X server and bringing
- * one down at the same time is a no go)
- */
- g_assert (self->priv->initial_login_operation == NULL);
- self->priv->initial_login_operation = operation;
- starting_user_session_right_away = FALSE;
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
!gdm_session_client_is_connected (operation->session)) {
/* remove the unused prepared greeter display since we're not going
* to have a greeter */
gdm_display_store_remove (self->priv->display_store, display);
g_object_unref (display);
}
/* Give the user session a new display object for bookkeeping purposes */
create_display_for_user_session (operation->manager,
operation->session,
session_id);
}
- if (starting_user_session_right_away) {
- start_user_session (operation->manager, operation);
- }
+ start_user_session (operation->manager, operation);
out:
return G_SOURCE_REMOVE;
}
static void
queue_start_user_session (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
StartUserSessionOperation *operation;
operation = g_slice_new0 (StartUserSessionOperation);
operation->manager = manager;
operation->session = g_object_ref (session);
operation->service_name = g_strdup (service_name);
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
}
static void
start_user_session_if_ready (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
gboolean start_when_ready;
start_when_ready = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (session), "start-when-ready"));
if (start_when_ready) {
--
2.27.0

View File

@ -1,309 +0,0 @@
From 3073c23c673ede5093c1f93fb0775c2cd3203d7f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 30 Aug 2018 16:09:02 -0400
Subject: [PATCH 28/51] gdm-wayland-session,gdm-x-session: register after delay
Right now gdm-x-session registers with GDM as soon as the
X server is started, and gdm-wayland-session registers as
soon as the session is started.
Ideally registration wouldn't happen until the session
says things started successfully.
This commit inches us toward that ideal but adding a little
timeout before proceeding with registration.
A future commit will add a new xsession file key to allow
us to know whether or not the session manager of the session
supports doing registration.
---
daemon/gdm-wayland-session.c | 23 ++++++++++++++++-------
daemon/gdm-x-session.c | 25 +++++++++++++++++--------
2 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
index 94f49e19c..de1991b34 100644
--- a/daemon/gdm-wayland-session.c
+++ b/daemon/gdm-wayland-session.c
@@ -427,60 +427,75 @@ init_state (State **state)
static State state_allocation;
*state = &state_allocation;
}
static void
clear_state (State **out_state)
{
State *state = *out_state;
g_clear_object (&state->cancellable);
g_clear_object (&state->bus_connection);
g_clear_object (&state->session_subprocess);
g_clear_pointer (&state->environment, g_strfreev);
g_clear_pointer (&state->main_loop, g_main_loop_unref);
*out_state = NULL;
}
static gboolean
on_sigterm (State *state)
{
g_cancellable_cancel (state->cancellable);
if (g_main_loop_is_running (state->main_loop)) {
g_main_loop_quit (state->main_loop);
}
return G_SOURCE_CONTINUE;
}
+static gboolean
+on_registration_delay_complete (State *state)
+{
+ gboolean ret;
+
+ ret = register_display (state, state->cancellable);
+
+ if (!ret) {
+ g_printerr ("Unable to register display with display manager\n");
+ g_main_loop_quit (state->main_loop);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
int
main (int argc,
char **argv)
{
State *state = NULL;
GOptionContext *context = NULL;
static char **args = NULL;
gboolean debug = FALSE;
gboolean ret;
int exit_status = EX_OK;
static GOptionEntry entries [] = {
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
{ NULL }
};
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
gdm_log_init ();
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
if (args == NULL || args[0] == NULL || args[1] != NULL) {
g_warning ("gdm-wayland-session takes one argument (the session)");
exit_status = EX_USAGE;
@@ -501,55 +516,49 @@ main (int argc,
}
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
state->debug_enabled = debug;
gdm_log_set_debug (debug);
state->main_loop = g_main_loop_new (NULL, FALSE);
state->cancellable = g_cancellable_new ();
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
ret = spawn_bus (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session message bus\n");
exit_status = EX_SOFTWARE;
goto out;
}
import_environment (state, state->cancellable);
ret = spawn_session (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session\n");
exit_status = EX_SOFTWARE;
goto out;
}
- ret = register_display (state, state->cancellable);
-
- if (!ret) {
- g_printerr ("Unable to register display with display manager\n");
- exit_status = EX_SOFTWARE;
- goto out;
- }
+ g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
g_main_loop_run (state->main_loop);
/* Only use exit status of session if we're here because it exit */
if (state->session_subprocess == NULL) {
exit_status = state->session_exit_status;
}
out:
if (state != NULL) {
signal_subprocesses (state);
wait_on_subprocesses (state);
clear_state (&state);
}
return exit_status;
}
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 3b2fcef47..412999cf5 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -783,60 +783,75 @@ init_state (State **state)
}
static void
clear_state (State **out_state)
{
State *state = *out_state;
g_clear_object (&state->cancellable);
g_clear_object (&state->bus_connection);
g_clear_object (&state->session_subprocess);
g_clear_object (&state->x_subprocess);
g_clear_pointer (&state->environment, g_strfreev);
g_clear_pointer (&state->auth_file, g_free);
g_clear_pointer (&state->display_name, g_free);
g_clear_pointer (&state->main_loop, g_main_loop_unref);
*out_state = NULL;
}
static gboolean
on_sigterm (State *state)
{
g_cancellable_cancel (state->cancellable);
if (g_main_loop_is_running (state->main_loop)) {
g_main_loop_quit (state->main_loop);
}
return G_SOURCE_CONTINUE;
}
+static gboolean
+on_registration_delay_complete (State *state)
+{
+ gboolean ret;
+
+ ret = register_display (state, state->cancellable);
+
+ if (!ret) {
+ g_printerr ("Unable to register display with display manager\n");
+ g_main_loop_quit (state->main_loop);
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
int
main (int argc,
char **argv)
{
State *state = NULL;
GOptionContext *context = NULL;
static char **args = NULL;
static gboolean run_script = FALSE;
static gboolean allow_remote_connections = FALSE;
gboolean debug = FALSE;
gboolean ret;
int exit_status = EX_OK;
static GOptionEntry entries [] = {
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
{ NULL }
};
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
gdm_log_init ();
context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
@@ -869,63 +884,57 @@ main (int argc,
state->cancellable = g_cancellable_new ();
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
if (!ret) {
g_printerr ("Unable to run X server\n");
exit_status = EX_SOFTWARE;
goto out;
}
ret = spawn_bus (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session message bus\n");
exit_status = EX_SOFTWARE;
goto out;
}
import_environment (state, state->cancellable);
ret = update_bus_environment (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to update bus environment\n");
exit_status = EX_SOFTWARE;
goto out;
}
- ret = register_display (state, state->cancellable);
-
- if (!ret) {
- g_printerr ("Unable to register display with display manager\n");
- exit_status = EX_SOFTWARE;
- goto out;
- }
-
ret = spawn_session (state, run_script, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session\n");
exit_status = EX_SOFTWARE;
goto out;
}
+ g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
+
g_main_loop_run (state->main_loop);
/* Only use exit status of session if we're here because it exit */
if (state->session_subprocess == NULL) {
exit_status = state->session_exit_status;
}
out:
if (state != NULL) {
signal_subprocesses (state);
wait_on_subprocesses (state);
clear_state (&state);
}
return exit_status;
}
--
2.27.0

View File

@ -1,399 +0,0 @@
From d85448e2e523deb1487e7e405a480e1c4e6a5f6f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 31 Aug 2018 15:33:00 -0400
Subject: [PATCH 29/51] local-display-factory: defer killing greeter until new
session registers
At the moment we kill the greeter the second the VT change to the new
session happens.
That can cause flicker if the new session doesn't take over the display
quickly enough.
This commit defers killing the greeter until the new display registers.
Closes https://gitlab.gnome.org/GNOME/gdm/issues/413
---
daemon/gdm-display.h | 1 +
daemon/gdm-local-display-factory.c | 43 +++++++++++++++++++++++++-----
2 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
index 6d5e88df9..33dc3be41 100644
--- a/daemon/gdm-display.h
+++ b/daemon/gdm-display.h
@@ -13,60 +13,61 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef __GDM_DISPLAY_H
#define __GDM_DISPLAY_H
#include <glib-object.h>
#include <gio/gio.h>
G_BEGIN_DECLS
#define GDM_TYPE_DISPLAY (gdm_display_get_type ())
#define GDM_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_DISPLAY, GdmDisplay))
#define GDM_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_DISPLAY, GdmDisplayClass))
#define GDM_IS_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_DISPLAY))
#define GDM_IS_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_DISPLAY))
#define GDM_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_DISPLAY, GdmDisplayClass))
typedef struct GdmDisplayPrivate GdmDisplayPrivate;
typedef enum {
GDM_DISPLAY_UNMANAGED = 0,
GDM_DISPLAY_PREPARED,
GDM_DISPLAY_MANAGED,
+ GDM_DISPLAY_WAITING_TO_FINISH,
GDM_DISPLAY_FINISHED,
GDM_DISPLAY_FAILED,
} GdmDisplayStatus;
typedef struct
{
GObject parent;
GdmDisplayPrivate *priv;
} GdmDisplay;
typedef struct
{
GObjectClass parent_class;
/* methods */
gboolean (*prepare) (GdmDisplay *display);
void (*manage) (GdmDisplay *self);
} GdmDisplayClass;
typedef enum
{
GDM_DISPLAY_ERROR_GENERAL,
GDM_DISPLAY_ERROR_GETTING_USER_INFO,
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
} GdmDisplayError;
#define GDM_DISPLAY_ERROR gdm_display_error_quark ()
GQuark gdm_display_error_quark (void);
GType gdm_display_get_type (void);
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 127127005..bc6ac6855 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -241,60 +241,90 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
display = gdm_legacy_display_new (num);
}
#endif
g_object_set (display,
"seat-id", "seat0",
"allow-timed-login", FALSE,
NULL);
store_display (factory, display);
if (! gdm_display_manage (display)) {
display = NULL;
goto out;
}
if (! gdm_display_get_id (display, id, NULL)) {
display = NULL;
goto out;
}
ret = TRUE;
out:
/* ref either held by store or not at all */
g_object_unref (display);
return ret;
}
+static gboolean
+finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
+ GdmDisplay *display,
+ const char *seat_id)
+{
+ if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
+ return FALSE;
+
+ g_debug ("GdmLocalDisplayFactory: finish background display\n");
+ gdm_display_stop_greeter_session (display);
+ gdm_display_unmanage (display);
+ gdm_display_finish (display);
+
+ return FALSE;
+}
+
+static void
+finish_waiting_displays_on_seat (GdmLocalDisplayFactory *factory,
+ const char *seat_id)
+{
+ GdmDisplayStore *store;
+
+ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+
+ gdm_display_store_foreach (store,
+ (GdmDisplayStoreFunc) finish_display_on_seat_if_waiting,
+ (gpointer)
+ seat_id);
+}
+
static void
on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory)
{
int status;
int num;
char *seat_id = NULL;
char *session_type = NULL;
char *session_class = NULL;
gboolean is_initial = TRUE;
gboolean is_local = TRUE;
num = -1;
gdm_display_get_x11_display_number (display, &num, NULL);
g_object_get (display,
"seat-id", &seat_id,
"is-initial", &is_initial,
"is-local", &is_local,
"session-type", &session_type,
"session-class", &session_class,
NULL);
status = gdm_display_get_status (display);
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
switch (status) {
case GDM_DISPLAY_FINISHED:
/* remove the display number from factory->priv->used_display_numbers
@@ -324,60 +354,63 @@ on_display_status_changed (GdmDisplay *display,
/* Create a new equivalent display if it was static */
if (is_local) {
factory->priv->num_failures++;
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
/* oh shit */
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
} else {
#ifdef ENABLE_WAYLAND_SUPPORT
if (g_strcmp0 (session_type, "wayland") == 0) {
g_free (session_type);
session_type = NULL;
/* workaround logind race for now
* bug 1643874
*/
g_usleep (2 * G_USEC_PER_SEC);
}
#endif
create_display (factory, seat_id, session_type, is_initial);
}
}
break;
case GDM_DISPLAY_UNMANAGED:
break;
case GDM_DISPLAY_PREPARED:
break;
case GDM_DISPLAY_MANAGED:
+ finish_waiting_displays_on_seat (factory, seat_id);
+ break;
+ case GDM_DISPLAY_WAITING_TO_FINISH:
break;
default:
g_assert_not_reached ();
break;
}
g_free (seat_id);
g_free (session_type);
g_free (session_class);
}
static gboolean
lookup_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
static gboolean
@@ -561,84 +594,82 @@ on_seat_new (GDBusConnection *connection,
static void
on_seat_removed (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *seat;
g_variant_get (parameters, "(&s&o)", &seat, NULL);
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
static gboolean
lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
const char *current;
current = gdm_display_get_session_id (display);
return g_strcmp0 (current, looking_for) == 0;
}
static void
-maybe_stop_greeter_display (GdmDisplay *display)
+maybe_stop_greeter_in_background (GdmDisplay *display)
{
g_autofree char *display_session_type = NULL;
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
return;
}
g_object_get (G_OBJECT (display),
"session-type", &display_session_type,
NULL);
/* we can only stop greeter for wayland sessions, since
* X server would jump back on exit */
if (g_strcmp0 (display_session_type, "wayland") != 0) {
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
return;
}
- g_debug ("GdmLocalDisplayFactory: killing login window since its now unused");
- gdm_display_stop_greeter_session (display);
- gdm_display_unmanage (display);
- gdm_display_finish (display);
+ g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
}
static gboolean
on_vt_changed (GIOChannel *source,
GIOCondition condition,
GdmLocalDisplayFactory *factory)
{
GIOStatus status;
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
g_autofree char *tty_of_previous_vt = NULL;
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
g_autofree char *active_session_id = NULL;
const char *session_type = NULL;
int ret;
g_debug ("GdmLocalDisplayFactory: received VT change event");
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
if (condition & G_IO_PRI) {
g_autoptr (GError) error = NULL;
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
if (error != NULL) {
g_warning ("could not read active VT from kernel: %s", error->message);
}
switch (status) {
case G_IO_STATUS_ERROR:
return G_SOURCE_REMOVE;
case G_IO_STATUS_EOF:
@@ -678,61 +709,61 @@ on_vt_changed (GIOChannel *source,
return G_SOURCE_CONTINUE;
}
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
tty_of_previous_vt, factory->priv->tty_of_active_vt);
/* if the old VT was running a wayland login screen kill it
*/
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
unsigned int vt;
ret = sd_session_get_vt (login_session_id, &vt);
if (ret == 0 && vt != 0) {
g_autofree char *tty_of_login_window_vt = NULL;
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
GdmDisplayStore *store;
GdmDisplay *display;
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL)
- maybe_stop_greeter_display (display);
+ maybe_stop_greeter_in_background (display);
} else {
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
}
}
}
/* if user jumped back to initial vt and it's empty put a login screen
* on it (unless a login screen is already running elsewhere, then
* jump to that login screen)
*/
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
if (ret == 0) {
g_autofree char *state = NULL;
ret = sd_session_get_state (active_session_id, &state);
/* if there's something already running on the active VT then bail */
if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
return G_SOURCE_CONTINUE;
}
}
if (gdm_local_display_factory_use_wayland ())
session_type = "wayland";
--
2.27.0

View File

@ -1,708 +0,0 @@
From 0ff911467265831006aac6216060dbecff84c1cb Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 4 Sep 2018 10:56:45 +0200
Subject: [PATCH 30/51] daemon: Move the waiting the session to have taken over
the fb to gdm-local-display-factory
Commit 708618746683 ("gdm-wayland-session,gdm-x-session: register after
delay") delayed displays changing their status from PREPARED to MANAGED
so that their status would not change until the session has had a change
to install its own framebuffer and tell the GPU to scanout this new fb.
Commit 74ee77717df7 ("local-display-factory: defer killing greeter until
new session registers") uses this to avoid a flicker when transitioning
from the greeter to the user-session by deferring the stopping of the
greeter-session until the new display moves to the MANAGED state.
But this only works when transitioning to a new user-session, when moving
to an existing user-session (fast user switching) the display already
is in MANAGED state and instead of deferring the stopping of the greeter
commit 74ee77717df7 causes us to now never stop the greeter-session.
This commit fixes this by starting a timeout when switching away from
the initial-vt and letting that timeout stop the greeter-session.
This commit removes the finish_waiting_displays_on_seat() call when the
display's status changes to MANAGED, so that we still only have one code
path stopping the greeter and not two.
This means we also no longer need to delay registering the display. So this
commit removes the code adding the delay (reverts commit 74ee77717df7).
Note this commit uses a delay of 10 seconds, rather then 2 seconds. The
transition to a new user-session takes about 8 seconds on my budget
Apollo Lake based laptop (with SSD).
Note this all really is a workaround, the proper solution for this would
be able to tell the kernel to keep the greeter framebuffer around until
a new framebuffer is installed. There is a patch to add a new unref_fb
ioctl for this: https://www.spinics.net/lists/dri-devel/msg140912.html .
We need to get this patch upstream and teach mutter to use it.
---
daemon/gdm-local-display-factory.c | 29 ++++++++++++++++++++++++++---
daemon/gdm-wayland-session.c | 23 +++++++----------------
daemon/gdm-x-session.c | 25 ++++++++-----------------
3 files changed, 41 insertions(+), 36 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index bc6ac6855..be6b377be 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -22,76 +22,78 @@
#include <stdlib.h>
#include <stdio.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <gio/gio.h>
#include <systemd/sd-login.h>
#include "gdm-common.h"
#include "gdm-manager.h"
#include "gdm-display-factory.h"
#include "gdm-local-display-factory.h"
#include "gdm-local-display-factory-glue.h"
#include "gdm-settings-keys.h"
#include "gdm-settings-direct.h"
#include "gdm-display-store.h"
#include "gdm-local-display.h"
#include "gdm-legacy-display.h"
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
#define MAX_DISPLAY_FAILURES 5
+#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
struct GdmLocalDisplayFactoryPrivate
{
GdmDBusLocalDisplayFactory *skeleton;
GDBusConnection *connection;
GHashTable *used_display_numbers;
/* FIXME: this needs to be per seat? */
guint num_failures;
guint seat_new_id;
guint seat_removed_id;
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
char *tty_of_active_vt;
guint active_vt_watch_id;
+ guint wait_to_finish_timeout_id;
#endif
};
enum {
PROP_0,
};
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
static void gdm_local_display_factory_finalize (GObject *object);
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial_display);
static void on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory);
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
static gpointer local_display_factory_object = NULL;
static gboolean lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data);
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
GQuark
gdm_local_display_factory_error_quark (void)
@@ -354,61 +356,60 @@ on_display_status_changed (GdmDisplay *display,
/* Create a new equivalent display if it was static */
if (is_local) {
factory->priv->num_failures++;
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
/* oh shit */
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
} else {
#ifdef ENABLE_WAYLAND_SUPPORT
if (g_strcmp0 (session_type, "wayland") == 0) {
g_free (session_type);
session_type = NULL;
/* workaround logind race for now
* bug 1643874
*/
g_usleep (2 * G_USEC_PER_SEC);
}
#endif
create_display (factory, seat_id, session_type, is_initial);
}
}
break;
case GDM_DISPLAY_UNMANAGED:
break;
case GDM_DISPLAY_PREPARED:
break;
case GDM_DISPLAY_MANAGED:
- finish_waiting_displays_on_seat (factory, seat_id);
break;
case GDM_DISPLAY_WAITING_TO_FINISH:
break;
default:
g_assert_not_reached ();
break;
}
g_free (seat_id);
g_free (session_type);
g_free (session_class);
}
static gboolean
lookup_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
char *current;
gboolean res;
g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
@@ -593,83 +594,101 @@ on_seat_new (GDBusConnection *connection,
}
static void
on_seat_removed (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
const gchar *interface_name,
const gchar *signal_name,
GVariant *parameters,
gpointer user_data)
{
const char *seat;
g_variant_get (parameters, "(&s&o)", &seat, NULL);
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
static gboolean
lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
const char *current;
current = gdm_display_get_session_id (display);
return g_strcmp0 (current, looking_for) == 0;
}
+static gboolean
+wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
+{
+ finish_waiting_displays_on_seat (factory, "seat0");
+ factory->priv->wait_to_finish_timeout_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
static void
-maybe_stop_greeter_in_background (GdmDisplay *display)
+maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
+ GdmDisplay *display)
{
g_autofree char *display_session_type = NULL;
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
return;
}
g_object_get (G_OBJECT (display),
"session-type", &display_session_type,
NULL);
/* we can only stop greeter for wayland sessions, since
* X server would jump back on exit */
if (g_strcmp0 (display_session_type, "wayland") != 0) {
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
return;
}
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
+
+ /* We stop the greeter after a timeout to avoid flicker */
+ if (factory->priv->wait_to_finish_timeout_id != 0)
+ g_source_remove (factory->priv->wait_to_finish_timeout_id);
+
+ factory->priv->wait_to_finish_timeout_id =
+ g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
+ (GSourceFunc)wait_to_finish_timeout,
+ factory);
}
static gboolean
on_vt_changed (GIOChannel *source,
GIOCondition condition,
GdmLocalDisplayFactory *factory)
{
GIOStatus status;
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
g_autofree char *tty_of_previous_vt = NULL;
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
g_autofree char *active_session_id = NULL;
const char *session_type = NULL;
int ret;
g_debug ("GdmLocalDisplayFactory: received VT change event");
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
if (condition & G_IO_PRI) {
g_autoptr (GError) error = NULL;
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
if (error != NULL) {
g_warning ("could not read active VT from kernel: %s", error->message);
}
switch (status) {
case G_IO_STATUS_ERROR:
return G_SOURCE_REMOVE;
case G_IO_STATUS_EOF:
@@ -709,61 +728,61 @@ on_vt_changed (GIOChannel *source,
return G_SOURCE_CONTINUE;
}
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
tty_of_previous_vt, factory->priv->tty_of_active_vt);
/* if the old VT was running a wayland login screen kill it
*/
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
unsigned int vt;
ret = sd_session_get_vt (login_session_id, &vt);
if (ret == 0 && vt != 0) {
g_autofree char *tty_of_login_window_vt = NULL;
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
GdmDisplayStore *store;
GdmDisplay *display;
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL)
- maybe_stop_greeter_in_background (display);
+ maybe_stop_greeter_in_background (factory, display);
} else {
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
}
}
}
/* if user jumped back to initial vt and it's empty put a login screen
* on it (unless a login screen is already running elsewhere, then
* jump to that login screen)
*/
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
if (ret == 0) {
g_autofree char *state = NULL;
ret = sd_session_get_state (active_session_id, &state);
/* if there's something already running on the active VT then bail */
if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
return G_SOURCE_CONTINUE;
}
}
if (gdm_local_display_factory_use_wayland ())
session_type = "wayland";
@@ -803,60 +822,64 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
g_object_unref);
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
if (io_channel != NULL) {
factory->priv->active_vt_watch_id =
g_io_add_watch (io_channel,
G_IO_PRI,
(GIOFunc)
on_vt_changed,
factory);
}
#endif
}
static void
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
{
if (factory->priv->seat_new_id) {
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
factory->priv->seat_new_id);
factory->priv->seat_new_id = 0;
}
if (factory->priv->seat_removed_id) {
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
factory->priv->seat_removed_id);
factory->priv->seat_removed_id = 0;
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ if (factory->priv->wait_to_finish_timeout_id != 0) {
+ g_source_remove (factory->priv->wait_to_finish_timeout_id);
+ factory->priv->wait_to_finish_timeout_id = 0;
+ }
if (factory->priv->active_vt_watch_id) {
g_source_remove (factory->priv->active_vt_watch_id);
factory->priv->active_vt_watch_id = 0;
}
g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
#endif
}
static void
on_display_added (GdmDisplayStore *display_store,
const char *id,
GdmLocalDisplayFactory *factory)
{
GdmDisplay *display;
display = gdm_display_store_lookup (display_store, id);
if (display != NULL) {
g_signal_connect_object (display, "notify::status",
G_CALLBACK (on_display_status_changed),
factory,
0);
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
index de1991b34..94f49e19c 100644
--- a/daemon/gdm-wayland-session.c
+++ b/daemon/gdm-wayland-session.c
@@ -427,75 +427,60 @@ init_state (State **state)
static State state_allocation;
*state = &state_allocation;
}
static void
clear_state (State **out_state)
{
State *state = *out_state;
g_clear_object (&state->cancellable);
g_clear_object (&state->bus_connection);
g_clear_object (&state->session_subprocess);
g_clear_pointer (&state->environment, g_strfreev);
g_clear_pointer (&state->main_loop, g_main_loop_unref);
*out_state = NULL;
}
static gboolean
on_sigterm (State *state)
{
g_cancellable_cancel (state->cancellable);
if (g_main_loop_is_running (state->main_loop)) {
g_main_loop_quit (state->main_loop);
}
return G_SOURCE_CONTINUE;
}
-static gboolean
-on_registration_delay_complete (State *state)
-{
- gboolean ret;
-
- ret = register_display (state, state->cancellable);
-
- if (!ret) {
- g_printerr ("Unable to register display with display manager\n");
- g_main_loop_quit (state->main_loop);
- }
-
- return G_SOURCE_REMOVE;
-}
-
int
main (int argc,
char **argv)
{
State *state = NULL;
GOptionContext *context = NULL;
static char **args = NULL;
gboolean debug = FALSE;
gboolean ret;
int exit_status = EX_OK;
static GOptionEntry entries [] = {
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
{ NULL }
};
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
gdm_log_init ();
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
if (args == NULL || args[0] == NULL || args[1] != NULL) {
g_warning ("gdm-wayland-session takes one argument (the session)");
exit_status = EX_USAGE;
@@ -516,49 +501,55 @@ main (int argc,
}
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
state->debug_enabled = debug;
gdm_log_set_debug (debug);
state->main_loop = g_main_loop_new (NULL, FALSE);
state->cancellable = g_cancellable_new ();
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
ret = spawn_bus (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session message bus\n");
exit_status = EX_SOFTWARE;
goto out;
}
import_environment (state, state->cancellable);
ret = spawn_session (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session\n");
exit_status = EX_SOFTWARE;
goto out;
}
- g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
+ ret = register_display (state, state->cancellable);
+
+ if (!ret) {
+ g_printerr ("Unable to register display with display manager\n");
+ exit_status = EX_SOFTWARE;
+ goto out;
+ }
g_main_loop_run (state->main_loop);
/* Only use exit status of session if we're here because it exit */
if (state->session_subprocess == NULL) {
exit_status = state->session_exit_status;
}
out:
if (state != NULL) {
signal_subprocesses (state);
wait_on_subprocesses (state);
clear_state (&state);
}
return exit_status;
}
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 412999cf5..3b2fcef47 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -783,75 +783,60 @@ init_state (State **state)
}
static void
clear_state (State **out_state)
{
State *state = *out_state;
g_clear_object (&state->cancellable);
g_clear_object (&state->bus_connection);
g_clear_object (&state->session_subprocess);
g_clear_object (&state->x_subprocess);
g_clear_pointer (&state->environment, g_strfreev);
g_clear_pointer (&state->auth_file, g_free);
g_clear_pointer (&state->display_name, g_free);
g_clear_pointer (&state->main_loop, g_main_loop_unref);
*out_state = NULL;
}
static gboolean
on_sigterm (State *state)
{
g_cancellable_cancel (state->cancellable);
if (g_main_loop_is_running (state->main_loop)) {
g_main_loop_quit (state->main_loop);
}
return G_SOURCE_CONTINUE;
}
-static gboolean
-on_registration_delay_complete (State *state)
-{
- gboolean ret;
-
- ret = register_display (state, state->cancellable);
-
- if (!ret) {
- g_printerr ("Unable to register display with display manager\n");
- g_main_loop_quit (state->main_loop);
- }
-
- return G_SOURCE_REMOVE;
-}
-
int
main (int argc,
char **argv)
{
State *state = NULL;
GOptionContext *context = NULL;
static char **args = NULL;
static gboolean run_script = FALSE;
static gboolean allow_remote_connections = FALSE;
gboolean debug = FALSE;
gboolean ret;
int exit_status = EX_OK;
static GOptionEntry entries [] = {
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
{ NULL }
};
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
setlocale (LC_ALL, "");
gdm_log_init ();
context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
g_option_context_add_main_entries (context, entries, NULL);
g_option_context_parse (context, &argc, &argv, NULL);
g_option_context_free (context);
@@ -884,57 +869,63 @@ main (int argc,
state->cancellable = g_cancellable_new ();
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
if (!ret) {
g_printerr ("Unable to run X server\n");
exit_status = EX_SOFTWARE;
goto out;
}
ret = spawn_bus (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session message bus\n");
exit_status = EX_SOFTWARE;
goto out;
}
import_environment (state, state->cancellable);
ret = update_bus_environment (state, state->cancellable);
if (!ret) {
g_printerr ("Unable to update bus environment\n");
exit_status = EX_SOFTWARE;
goto out;
}
+ ret = register_display (state, state->cancellable);
+
+ if (!ret) {
+ g_printerr ("Unable to register display with display manager\n");
+ exit_status = EX_SOFTWARE;
+ goto out;
+ }
+
ret = spawn_session (state, run_script, state->cancellable);
if (!ret) {
g_printerr ("Unable to run session\n");
exit_status = EX_SOFTWARE;
goto out;
}
- g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
-
g_main_loop_run (state->main_loop);
/* Only use exit status of session if we're here because it exit */
if (state->session_subprocess == NULL) {
exit_status = state->session_exit_status;
}
out:
if (state != NULL) {
signal_subprocesses (state);
wait_on_subprocesses (state);
clear_state (&state);
}
return exit_status;
}
--
2.27.0

View File

@ -1,100 +0,0 @@
From 59b3b809400dfac25410cf99dbc15cb5f66f85a3 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 25 Sep 2018 14:52:15 -0400
Subject: [PATCH 31/51] local-display-factory: don't autoreap initial-setup
We automatically kill the login screen when switching VTs away
from it, but we should never kill the initial-setup screen in
that situation.
This commit adds a check to prevent that from happening.
---
daemon/gdm-local-display-factory.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index be6b377be..13d56dcff 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -607,70 +607,78 @@ on_seat_removed (GDBusConnection *connection,
g_variant_get (parameters, "(&s&o)", &seat, NULL);
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
static gboolean
lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
const char *current;
current = gdm_display_get_session_id (display);
return g_strcmp0 (current, looking_for) == 0;
}
static gboolean
wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
{
finish_waiting_displays_on_seat (factory, "seat0");
factory->priv->wait_to_finish_timeout_id = 0;
return G_SOURCE_REMOVE;
}
static void
maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
GdmDisplay *display)
{
g_autofree char *display_session_type = NULL;
+ gboolean doing_initial_setup = FALSE;
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
return;
}
g_object_get (G_OBJECT (display),
"session-type", &display_session_type,
+ "doing-initial-setup", &doing_initial_setup,
NULL);
+ /* we don't ever stop initial-setup implicitly */
+ if (doing_initial_setup) {
+ g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
+ return;
+ }
+
/* we can only stop greeter for wayland sessions, since
* X server would jump back on exit */
if (g_strcmp0 (display_session_type, "wayland") != 0) {
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
return;
}
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
/* We stop the greeter after a timeout to avoid flicker */
if (factory->priv->wait_to_finish_timeout_id != 0)
g_source_remove (factory->priv->wait_to_finish_timeout_id);
factory->priv->wait_to_finish_timeout_id =
g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
(GSourceFunc)wait_to_finish_timeout,
factory);
}
static gboolean
on_vt_changed (GIOChannel *source,
GIOCondition condition,
GdmLocalDisplayFactory *factory)
{
GIOStatus status;
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
g_autofree char *tty_of_previous_vt = NULL;
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
--
2.27.0

View File

@ -1,460 +0,0 @@
From 566720ce07db8745c0ae6780ff289292dc0a9b60 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 25 Sep 2018 10:59:37 -0400
Subject: [PATCH 32/51] manager: rework how autologin is figured out
At the moment we decide whether or not to perform autologin, by
looking at if the display is the initial VT display and if autologin
hasn't been started before.
That isn't going to work in the future when autologin is started
on a non-initial vt.
This commit changes GDM to instead check if the seat is seat0, and
if autologin hasn't run before, before deciding to do autologin.
---
daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++------------
1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index fb7b1ec4b..228cec6ff 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -51,75 +51,76 @@
#include "gdm-session.h"
#include "gdm-session-record.h"
#include "gdm-settings-direct.h"
#include "gdm-settings-keys.h"
#include "gdm-xdmcp-display-factory.h"
#include "gdm-xdmcp-chooser-display.h"
#define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager"
#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
typedef struct
{
GdmManager *manager;
GdmSession *session;
char *service_name;
guint idle_id;
} StartUserSessionOperation;
struct GdmManagerPrivate
{
GdmDisplayStore *display_store;
GdmLocalDisplayFactory *local_factory;
#ifdef HAVE_LIBXDMCP
GdmXdmcpDisplayFactory *xdmcp_factory;
#endif
+ GdmDisplay *automatic_login_display;
GList *user_sessions;
GHashTable *transient_sessions;
GHashTable *open_reauthentication_requests;
gboolean xdmcp_enabled;
gboolean started;
gboolean show_local_greeter;
GDBusConnection *connection;
GDBusObjectManagerServer *object_manager;
#ifdef WITH_PLYMOUTH
guint plymouth_is_running : 1;
#endif
- guint ran_once : 1;
+ guint did_automatic_login : 1;
};
enum {
PROP_0,
PROP_XDMCP_ENABLED,
PROP_SHOW_LOCAL_GREETER
};
enum {
DISPLAY_ADDED,
DISPLAY_REMOVED,
LAST_SIGNAL
};
typedef enum {
SESSION_RECORD_LOGIN,
SESSION_RECORD_LOGOUT,
SESSION_RECORD_FAILED,
} SessionRecord;
static guint signals [LAST_SIGNAL] = { 0, };
static void gdm_manager_class_init (GdmManagerClass *klass);
static void gdm_manager_init (GdmManager *manager);
static void gdm_manager_dispose (GObject *object);
static GdmSession *create_user_session_for_display (GdmManager *manager,
GdmDisplay *display,
uid_t allowed_user);
static void start_user_session (GdmManager *manager,
@@ -1415,67 +1416,74 @@ typedef struct {
static void
destroy_username_lookup_operation (UsernameLookupOperation *operation)
{
g_object_unref (operation->manager);
g_object_unref (operation->display);
g_free (operation->username);
g_free (operation);
}
static void
on_user_is_loaded_changed (ActUser *user,
GParamSpec *pspec,
UsernameLookupOperation *operation)
{
if (act_user_is_loaded (user)) {
set_up_automatic_login_session_if_user_exists (operation->manager, operation->display, user);
g_signal_handlers_disconnect_by_func (G_OBJECT (user),
G_CALLBACK (on_user_is_loaded_changed),
operation);
destroy_username_lookup_operation (operation);
}
}
static void
set_up_session (GdmManager *manager,
GdmDisplay *display)
{
ActUserManager *user_manager;
ActUser *user;
gboolean loaded;
- gboolean is_initial_display = FALSE;
+ gboolean seat_can_autologin = FALSE, seat_did_autologin = FALSE;
gboolean autologin_enabled = FALSE;
+ g_autofree char *seat_id = NULL;
char *username = NULL;
- g_object_get (G_OBJECT (display), "is-initial", &is_initial_display, NULL);
+ g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
+
+ if (g_strcmp0 (seat_id, "seat0") == 0)
+ seat_can_autologin = TRUE;
+
+ if (manager->priv->did_automatic_login || manager->priv->automatic_login_display != NULL)
+ seat_did_autologin = TRUE;
- if (!manager->priv->ran_once && is_initial_display)
+ if (seat_can_autologin && !seat_did_autologin)
autologin_enabled = get_automatic_login_details (manager, &username);
if (!autologin_enabled) {
g_free (username);
#ifdef HAVE_LIBXDMCP
if (GDM_IS_XDMCP_CHOOSER_DISPLAY (display)) {
set_up_chooser_session (manager, display);
return;
}
#endif
set_up_greeter_session (manager, display);
return;
}
/* Check whether the user really exists before committing to autologin. */
user_manager = act_user_manager_get_default ();
user = act_user_manager_get_user (user_manager, username);
g_object_get (user_manager, "is-loaded", &loaded, NULL);
if (loaded) {
set_up_automatic_login_session_if_user_exists (manager, display, user);
} else {
UsernameLookupOperation *operation;
operation = g_new (UsernameLookupOperation, 1);
operation->manager = g_object_ref (manager);
operation->display = g_object_ref (display);
operation->username = username;
@@ -1512,62 +1520,72 @@ on_display_status_changed (GdmDisplay *display,
"session-type", &session_type,
NULL);
status = gdm_display_get_status (display);
switch (status) {
case GDM_DISPLAY_PREPARED:
case GDM_DISPLAY_MANAGED:
if ((display_number == -1 && status == GDM_DISPLAY_PREPARED) ||
(display_number != -1 && status == GDM_DISPLAY_MANAGED)) {
char *session_class;
g_object_get (display,
"session-class", &session_class,
NULL);
if (g_strcmp0 (session_class, "greeter") == 0)
set_up_session (manager, display);
g_free (session_class);
}
break;
case GDM_DISPLAY_FAILED:
case GDM_DISPLAY_UNMANAGED:
case GDM_DISPLAY_FINISHED:
#ifdef WITH_PLYMOUTH
if (quit_plymouth) {
plymouth_quit_without_transition ();
manager->priv->plymouth_is_running = FALSE;
}
#endif
- if (!doing_initial_setup && (status == GDM_DISPLAY_FINISHED || g_strcmp0 (session_type, "x11") == 0)) {
- manager->priv->ran_once = TRUE;
+ if (display == manager->priv->automatic_login_display) {
+ g_clear_weak_pointer (&manager->priv->automatic_login_display);
+
+ manager->priv->did_automatic_login = TRUE;
+
+#ifdef ENABLE_WAYLAND_SUPPORT
+ if (g_strcmp0 (session_type, "wayland") != 0 && status == GDM_DISPLAY_FAILED) {
+ /* we're going to fall back to X11, so try to autologin again
+ */
+ manager->priv->did_automatic_login = FALSE;
+ }
+#endif
}
break;
default:
break;
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmManager *manager)
{
char *id;
gdm_display_get_id (display, &id, NULL);
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
g_free (id);
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), manager);
g_signal_emit (manager, signals[DISPLAY_REMOVED], 0, display);
}
static void
destroy_start_user_session_operation (StartUserSessionOperation *operation)
{
g_object_set_data (G_OBJECT (operation->session),
"start-user-session-operation",
NULL);
@@ -1621,132 +1639,134 @@ create_display_for_user_session (GdmManager *self,
const char *session_id)
{
GdmDisplay *display;
/* at the moment we only create GdmLocalDisplay objects on seat0 */
const char *seat_id = "seat0";
display = gdm_local_display_new ();
g_object_set (G_OBJECT (display),
"session-class", "user",
"seat-id", seat_id,
"session-id", session_id,
NULL);
gdm_display_store_add (self->priv->display_store,
display);
g_object_set_data (G_OBJECT (session), "gdm-display", display);
g_object_set_data_full (G_OBJECT (display),
"gdm-user-session",
g_object_ref (session),
(GDestroyNotify)
clean_user_session);
}
static gboolean
on_start_user_session (StartUserSessionOperation *operation)
{
GdmManager *self = operation->manager;
gboolean migrated;
gboolean fail_if_already_switched = TRUE;
gboolean doing_initial_setup = FALSE;
- gboolean starting_user_session_right_away = TRUE;
GdmDisplay *display;
const char *session_id;
g_debug ("GdmManager: start or jump to session");
/* If there's already a session running, jump to it.
* If the only session running is the one we just opened,
* start a session on it.
*/
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
g_debug ("GdmManager: migrated: %d", migrated);
if (migrated) {
/* We don't stop the manager here because
when Xorg exits it switches to the VT it was
started from. That interferes with fast
user switching. */
gdm_session_reset (operation->session);
destroy_start_user_session_operation (operation);
goto out;
}
display = get_display_for_user_session (operation->session);
g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
session_id = gdm_session_get_conversation_session_id (operation->session,
operation->service_name);
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
/* In this case, the greeter's display is morphing into
* the user session display. Kill the greeter on this session
* and let the user session follow the same display. */
gdm_display_stop_greeter_session (display);
g_object_set (G_OBJECT (display),
"session-class", "user",
"session-id", session_id,
NULL);
} else {
uid_t allowed_uid;
g_object_ref (display);
if (doing_initial_setup) {
g_debug ("GdmManager: closing down initial setup display");
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
+ /* Give the user session a new display object for bookkeeping purposes */
+ create_display_for_user_session (operation->manager,
+ operation->session,
+ session_id);
+
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
!gdm_session_client_is_connected (operation->session)) {
/* remove the unused prepared greeter display since we're not going
* to have a greeter */
gdm_display_store_remove (self->priv->display_store, display);
g_object_unref (display);
- }
- /* Give the user session a new display object for bookkeeping purposes */
- create_display_for_user_session (operation->manager,
- operation->session,
- session_id);
+ self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
+ g_object_add_weak_pointer (G_OBJECT (display), (gpointer *) &self->priv->automatic_login_display);
+ }
}
start_user_session (operation->manager, operation);
out:
return G_SOURCE_REMOVE;
}
static void
queue_start_user_session (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
StartUserSessionOperation *operation;
operation = g_slice_new0 (StartUserSessionOperation);
operation->manager = manager;
operation->session = g_object_ref (session);
operation->service_name = g_strdup (service_name);
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
}
static void
start_user_session_if_ready (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
gboolean start_when_ready;
@@ -2601,60 +2621,62 @@ unexport_display (const char *id,
GdmDisplay *display,
GdmManager *manager)
{
if (!g_dbus_connection_is_closed (manager->priv->connection))
g_dbus_object_manager_server_unexport (manager->priv->object_manager, id);
}
static void
finish_display (const char *id,
GdmDisplay *display,
GdmManager *manager)
{
gdm_display_stop_greeter_session (display);
if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED)
gdm_display_unmanage (display);
gdm_display_finish (display);
}
static void
gdm_manager_dispose (GObject *object)
{
GdmManager *manager;
g_return_if_fail (object != NULL);
g_return_if_fail (GDM_IS_MANAGER (object));
manager = GDM_MANAGER (object);
g_return_if_fail (manager->priv != NULL);
+ g_clear_weak_pointer (&manager->priv->automatic_login_display);
+
#ifdef HAVE_LIBXDMCP
g_clear_object (&manager->priv->xdmcp_factory);
#endif
g_clear_object (&manager->priv->local_factory);
g_clear_pointer (&manager->priv->open_reauthentication_requests,
(GDestroyNotify)
g_hash_table_unref);
g_clear_pointer (&manager->priv->transient_sessions,
(GDestroyNotify)
g_hash_table_unref);
g_list_foreach (manager->priv->user_sessions,
(GFunc) gdm_session_close,
NULL);
g_list_free_full (manager->priv->user_sessions, (GDestroyNotify) g_object_unref);
manager->priv->user_sessions = NULL;
g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
G_CALLBACK (on_display_added),
manager);
g_signal_handlers_disconnect_by_func (G_OBJECT (manager->priv->display_store),
G_CALLBACK (on_display_removed),
manager);
if (!g_dbus_connection_is_closed (manager->priv->connection)) {
gdm_display_store_foreach (manager->priv->display_store,
(GdmDisplayStoreFunc)unexport_display,
manager);
g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (manager));
}
--
2.27.0

View File

@ -1,85 +0,0 @@
From 05e49542a9de81731fce68614babe22d437e8fff Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 1 Oct 2018 11:05:57 -0400
Subject: [PATCH 33/51] manager: correct display confusion
commit c5c5bf1f reworked autologin and broke it.
This commit addresses the breakage by accessing
the proper display variable.
Closes https://gitlab.gnome.org/GNOME/gdm/issues/426
---
daemon/gdm-manager.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 228cec6ff..4c81dac7f 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1711,61 +1711,61 @@ on_start_user_session (StartUserSessionOperation *operation)
if (doing_initial_setup) {
g_debug ("GdmManager: closing down initial setup display");
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
/* Give the user session a new display object for bookkeeping purposes */
create_display_for_user_session (operation->manager,
operation->session,
session_id);
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
!gdm_session_client_is_connected (operation->session)) {
/* remove the unused prepared greeter display since we're not going
* to have a greeter */
gdm_display_store_remove (self->priv->display_store, display);
g_object_unref (display);
self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
- g_object_add_weak_pointer (G_OBJECT (display), (gpointer *) &self->priv->automatic_login_display);
+ g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
}
}
start_user_session (operation->manager, operation);
out:
return G_SOURCE_REMOVE;
}
static void
queue_start_user_session (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
StartUserSessionOperation *operation;
operation = g_slice_new0 (StartUserSessionOperation);
operation->manager = manager;
operation->session = g_object_ref (session);
operation->service_name = g_strdup (service_name);
operation->idle_id = g_idle_add ((GSourceFunc) on_start_user_session, operation);
g_object_set_data (G_OBJECT (session), "start-user-session-operation", operation);
}
static void
start_user_session_if_ready (GdmManager *manager,
GdmSession *session,
const char *service_name)
{
--
2.27.0

View File

@ -1,99 +0,0 @@
From e4c9a998f89d429d31b02997f146c8218c0742bc Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 24 Sep 2018 14:45:38 -0400
Subject: [PATCH 34/51] manager: don't run autologin display on tty1
tty1 is really meant for the login screen.
If a user autologins on it and we need a login
screen later, then the login screen has to go
in some auxiliary VT which isn't very nice.
This commit changes autologin to not use the
initial vt.
---
daemon/gdm-manager.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 4c81dac7f..e896c8945 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1308,74 +1308,72 @@ get_automatic_login_details (GdmManager *manager,
} else {
g_free (username);
}
return enabled;
}
static const char *
get_username_for_greeter_display (GdmManager *manager,
GdmDisplay *display)
{
gboolean doing_initial_setup = FALSE;
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
NULL);
if (doing_initial_setup) {
return INITIAL_SETUP_USERNAME;
} else {
return GDM_USERNAME;
}
}
static void
set_up_automatic_login_session (GdmManager *manager,
GdmDisplay *display)
{
GdmSession *session;
char *display_session_type = NULL;
- gboolean is_initial;
/* 0 is root user; since the daemon talks to the session object
* directly, itself, for automatic login
*/
session = create_user_session_for_display (manager, display, 0);
g_object_get (G_OBJECT (display),
- "is-initial", &is_initial,
"session-type", &display_session_type,
NULL);
g_object_set (G_OBJECT (session),
- "display-is-initial", is_initial,
+ "display-is-initial", FALSE,
NULL);
g_debug ("GdmManager: Starting automatic login conversation");
gdm_session_start_conversation (session, "gdm-autologin");
}
static void
set_up_chooser_session (GdmManager *manager,
GdmDisplay *display)
{
const char *allowed_user;
struct passwd *passwd_entry;
allowed_user = get_username_for_greeter_display (manager, display);
if (!gdm_get_pwent_for_name (allowed_user, &passwd_entry)) {
g_warning ("GdmManager: couldn't look up username %s",
allowed_user);
gdm_display_unmanage (display);
gdm_display_finish (display);
return;
}
gdm_display_start_greeter_session (display);
}
static void
set_up_greeter_session (GdmManager *manager,
GdmDisplay *display)
{
--
2.27.0

View File

@ -1,110 +0,0 @@
From 2843a951ef826afd01fa3c7340780b1929db38c7 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 4 Sep 2018 08:12:34 +0200
Subject: [PATCH 35/51] local-display-factory: Remove initial VT is in use
check
The initial VT is in use check in on_vt_changed() is racy, when switching
to VT1 from an active session, on_vt_changed() may run before logind has
processed the VT change and then sd_seat_get_active() will return the
active session which we are switching away from. This results in the greeter
not being started on VT1.
On my system gdm reliably wins the race resulting in not getting a greeter
when manually switching from an active session to VT1.
gdm already starts the greeter unconditionally from
gdm_local_display_factory_sync_seats() on both startup and when an user
session exits. gdm also starts it unconditionally when selecting
"Switch user" from an user session.
Now autologin sessions avoid the initial VT as well.
So we now can assume that the initial VT is free for the login screen's
use. And create_display already checks for and re-uses
an existing greeter, so we can safely remove the racy check.
---
daemon/gdm-local-display-factory.c | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 13d56dcff..8e46dbca2 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -752,73 +752,60 @@ on_vt_changed (GIOChannel *source,
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
GdmDisplayStore *store;
GdmDisplay *display;
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL)
maybe_stop_greeter_in_background (factory, display);
} else {
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
}
}
}
/* if user jumped back to initial vt and it's empty put a login screen
* on it (unless a login screen is already running elsewhere, then
* jump to that login screen)
*/
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
- ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
-
- if (ret == 0) {
- g_autofree char *state = NULL;
- ret = sd_session_get_state (active_session_id, &state);
-
- /* if there's something already running on the active VT then bail */
- if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
- g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
- return G_SOURCE_CONTINUE;
- }
- }
-
if (gdm_local_display_factory_use_wayland ())
session_type = "wayland";
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
create_display (factory, "seat0", session_type, TRUE);
return G_SOURCE_CONTINUE;
}
#endif
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatNew",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_new,
g_object_ref (factory),
g_object_unref);
factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatRemoved",
--
2.27.0

View File

@ -1,140 +0,0 @@
From f5acee2766c05403235c06da6b1bb68af744da79 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 25 Sep 2018 14:30:16 -0400
Subject: [PATCH 36/51] local-display-factory: Remove same VT so don't switch
check
We avoid changing to the login screen vt if we're already on it,
but the call is racy since we react to vt changes concurrently
with logind (who we query for the active vt).
This check drops the active vt check since it's pointless and
getting in the way.
---
daemon/gdm-local-display-factory.c | 39 ++++++++++--------------------
1 file changed, 13 insertions(+), 26 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 8e46dbca2..be7b43cff 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -410,103 +410,90 @@ lookup_by_seat_id (const char *id,
res = g_strcmp0 (current, looking_for) == 0;
g_free(current);
return res;
}
static gboolean
lookup_prepared_display_by_seat_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
int status;
status = gdm_display_get_status (display);
if (status != GDM_DISPLAY_PREPARED)
return FALSE;
return lookup_by_seat_id (id, display, user_data);
}
static GdmDisplay *
create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
- char *active_session_id = NULL;
- int ret;
+ g_autofree char *login_session_id = NULL;
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
session_type? : "X11", seat_id);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
if (sd_seat_can_multi_session (seat_id))
display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
else
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
/* Ensure we don't create the same display more than once */
if (display != NULL) {
g_debug ("GdmLocalDisplayFactory: display already created");
return NULL;
}
- ret = sd_seat_get_active (seat_id, &active_session_id, NULL);
-
- if (ret == 0) {
- char *login_session_id = NULL;
-
- /* If we already have a login window, switch to it */
- if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
- GdmDisplay *display;
-
- display = gdm_display_store_find (store,
- lookup_by_session_id,
- (gpointer) login_session_id);
- if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
- if (g_strcmp0 (active_session_id, login_session_id) != 0) {
- g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
- login_session_id);
- gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
- }
- g_clear_pointer (&login_session_id, g_free);
- g_clear_pointer (&active_session_id, g_free);
- return NULL;
- }
- g_clear_pointer (&login_session_id, g_free);
+ /* If we already have a login window, switch to it */
+ if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
+ GdmDisplay *display;
+
+ display = gdm_display_store_find (store,
+ lookup_by_session_id,
+ (gpointer) login_session_id);
+ if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
+ g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
+ login_session_id);
+ gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
+ return NULL;
}
- g_clear_pointer (&active_session_id, g_free);
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
g_object_set (display, "seat-id", seat_id, NULL);
g_object_set (display, "is-initial", initial, NULL);
store_display (factory, display);
/* let store own the ref */
g_object_unref (display);
if (! gdm_display_manage (display)) {
--
2.27.0

View File

@ -1,88 +0,0 @@
From 59a4538e335362a92186217be03529f3694697e1 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Tue, 25 Sep 2018 14:39:42 -0400
Subject: [PATCH 37/51] local-display-factory: handle reviving displays that
are waiting to die
We may end up re-using a display in waiting-to-finish state before it gets
finished in this case reset its state to managed to avoid it getting
finished while it is being used.
Closes https://gitlab.gnome.org/GNOME/gdm/merge_requests/45
---
daemon/gdm-local-display-factory.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index be7b43cff..d999596b5 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -434,61 +434,64 @@ create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial)
{
GdmDisplayStore *store;
GdmDisplay *display = NULL;
g_autofree char *login_session_id = NULL;
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
session_type? : "X11", seat_id);
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
if (sd_seat_can_multi_session (seat_id))
display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
else
display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
/* Ensure we don't create the same display more than once */
if (display != NULL) {
g_debug ("GdmLocalDisplayFactory: display already created");
return NULL;
}
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
GdmDisplay *display;
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
- if (display != NULL && gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
+ if (display != NULL &&
+ (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED ||
+ gdm_display_get_status (display) == GDM_DISPLAY_WAITING_TO_FINISH)) {
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL);
g_debug ("GdmLocalDisplayFactory: session %s found, activating.",
login_session_id);
gdm_activate_session_by_id (factory->priv->connection, seat_id, login_session_id);
return NULL;
}
}
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (seat_id, "seat0") == 0) {
display = gdm_local_display_new ();
if (session_type != NULL) {
g_object_set (G_OBJECT (display), "session-type", session_type, NULL);
}
}
#endif
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
g_object_set (display, "seat-id", seat_id, NULL);
g_object_set (display, "is-initial", initial, NULL);
store_display (factory, display);
--
2.27.0

View File

@ -1,151 +0,0 @@
From c65a0dbd195be52f0db0c49ea0355fe1b5eb4c09 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 31 Aug 2018 15:48:38 -0400
Subject: [PATCH 38/51] manager: don't kill initial-setup before starting user
session on wayland
Right now we kill initial-setup before starting the session for the user
initial-setup created. This is the right thing to do for Xorg, since
Xorg can't be killed in the background, but it adds unncessary flicker
for wayland.
This commit checks if it's wayland and avoids killing it right away
in that case.
---
daemon/gdm-manager.c | 26 +++++++++++++++++++++-----
1 file changed, 21 insertions(+), 5 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index e896c8945..0823e8638 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1639,105 +1639,121 @@ create_display_for_user_session (GdmManager *self,
GdmDisplay *display;
/* at the moment we only create GdmLocalDisplay objects on seat0 */
const char *seat_id = "seat0";
display = gdm_local_display_new ();
g_object_set (G_OBJECT (display),
"session-class", "user",
"seat-id", seat_id,
"session-id", session_id,
NULL);
gdm_display_store_add (self->priv->display_store,
display);
g_object_set_data (G_OBJECT (session), "gdm-display", display);
g_object_set_data_full (G_OBJECT (display),
"gdm-user-session",
g_object_ref (session),
(GDestroyNotify)
clean_user_session);
}
static gboolean
on_start_user_session (StartUserSessionOperation *operation)
{
GdmManager *self = operation->manager;
gboolean migrated;
gboolean fail_if_already_switched = TRUE;
gboolean doing_initial_setup = FALSE;
GdmDisplay *display;
const char *session_id;
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ g_autofree char *display_session_type = NULL;
+#endif
g_debug ("GdmManager: start or jump to session");
/* If there's already a session running, jump to it.
* If the only session running is the one we just opened,
* start a session on it.
*/
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
g_debug ("GdmManager: migrated: %d", migrated);
if (migrated) {
/* We don't stop the manager here because
when Xorg exits it switches to the VT it was
started from. That interferes with fast
user switching. */
gdm_session_reset (operation->session);
destroy_start_user_session_operation (operation);
goto out;
}
display = get_display_for_user_session (operation->session);
- g_object_get (G_OBJECT (display), "doing-initial-setup", &doing_initial_setup, NULL);
+ g_object_get (G_OBJECT (display),
+ "doing-initial-setup", &doing_initial_setup,
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ "session-type", &display_session_type,
+#endif
+ NULL);
session_id = gdm_session_get_conversation_session_id (operation->session,
operation->service_name);
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
/* In this case, the greeter's display is morphing into
* the user session display. Kill the greeter on this session
* and let the user session follow the same display. */
gdm_display_stop_greeter_session (display);
g_object_set (G_OBJECT (display),
"session-class", "user",
"session-id", session_id,
NULL);
} else {
uid_t allowed_uid;
g_object_ref (display);
if (doing_initial_setup) {
- g_debug ("GdmManager: closing down initial setup display");
- gdm_display_stop_greeter_session (display);
- gdm_display_unmanage (display);
- gdm_display_finish (display);
+#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
+ if (g_strcmp0 (display_session_type, "wayland") == 0) {
+ g_debug ("GdmManager: closing down initial setup display in background");
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
+ }
+#endif
+ if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
+ g_debug ("GdmManager: closing down initial setup display");
+ gdm_display_stop_greeter_session (display);
+ gdm_display_unmanage (display);
+ gdm_display_finish (display);
+ }
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
/* Give the user session a new display object for bookkeeping purposes */
create_display_for_user_session (operation->manager,
operation->session,
session_id);
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
!gdm_session_client_is_connected (operation->session)) {
/* remove the unused prepared greeter display since we're not going
* to have a greeter */
gdm_display_store_remove (self->priv->display_store, display);
g_object_unref (display);
self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
}
}
start_user_session (operation->manager, operation);
--
2.27.0

View File

@ -1,694 +0,0 @@
From c08afca0807d8820030c19a40e7590f72878c788 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 6 Sep 2018 19:31:50 -0400
Subject: [PATCH 39/51] manager: do initial-setup post work in manager code
Right now we do the initial-setup related post work
when stopping the greeter, but the problem is we delay
stopping the greeter now until after the user session
is started.
That post-work needs to be done before the user session
is started.
This commit moves the code to a more logical place.
---
daemon/gdm-display.c | 132 -------------------------------------------
daemon/gdm-manager.c | 132 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 132 insertions(+), 132 deletions(-)
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 875534272..1cef8c7c1 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -22,61 +22,60 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <glib.h>
#include <glib/gi18n.h>
#include <glib-object.h>
#include <xcb/xcb.h>
#include <X11/Xlib.h>
#include "gdm-common.h"
#include "gdm-display.h"
#include "gdm-display-glue.h"
#include "gdm-display-access-file.h"
#include "gdm-launch-environment.h"
#include "gdm-settings-direct.h"
#include "gdm-settings-keys.h"
#include "gdm-launch-environment.h"
#include "gdm-dbus-util.h"
-#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
#define GNOME_SESSION_SESSIONS_PATH DATADIR "/gnome-session/sessions"
#define GDM_DISPLAY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_DISPLAY, GdmDisplayPrivate))
struct GdmDisplayPrivate
{
char *id;
char *seat_id;
char *session_id;
char *session_class;
char *session_type;
char *remote_hostname;
int x11_display_number;
char *x11_display_name;
int status;
time_t creation_time;
GTimer *server_timer;
char *x11_cookie;
gsize x11_cookie_size;
GdmDisplayAccessFile *access_file;
guint finish_idle_id;
xcb_connection_t *xcb_connection;
int xcb_screen_number;
GDBusConnection *connection;
GdmDisplayAccessFile *user_access_file;
@@ -98,131 +97,60 @@ enum {
PROP_0,
PROP_ID,
PROP_STATUS,
PROP_SEAT_ID,
PROP_SESSION_ID,
PROP_SESSION_CLASS,
PROP_SESSION_TYPE,
PROP_REMOTE_HOSTNAME,
PROP_X11_DISPLAY_NUMBER,
PROP_X11_DISPLAY_NAME,
PROP_X11_COOKIE,
PROP_X11_AUTHORITY_FILE,
PROP_IS_CONNECTED,
PROP_IS_LOCAL,
PROP_LAUNCH_ENVIRONMENT,
PROP_IS_INITIAL,
PROP_ALLOW_TIMED_LOGIN,
PROP_HAVE_EXISTING_USER_ACCOUNTS,
PROP_DOING_INITIAL_SETUP,
};
static void gdm_display_class_init (GdmDisplayClass *klass);
static void gdm_display_init (GdmDisplay *self);
static void gdm_display_finalize (GObject *object);
static void queue_finish (GdmDisplay *self);
static void _gdm_display_set_status (GdmDisplay *self,
int status);
static gboolean wants_initial_setup (GdmDisplay *self);
G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
-static gboolean
-chown_file (GFile *file,
- uid_t uid,
- gid_t gid,
- GError **error)
-{
- if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, error)) {
- return FALSE;
- }
- if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, error)) {
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-chown_recursively (GFile *dir,
- uid_t uid,
- gid_t gid,
- GError **error)
-{
- GFile *file = NULL;
- GFileInfo *info = NULL;
- GFileEnumerator *enumerator = NULL;
- gboolean retval = FALSE;
-
- if (chown_file (dir, uid, gid, error) == FALSE) {
- goto out;
- }
-
- enumerator = g_file_enumerate_children (dir,
- G_FILE_ATTRIBUTE_STANDARD_TYPE","
- G_FILE_ATTRIBUTE_STANDARD_NAME,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL, error);
- if (!enumerator) {
- goto out;
- }
-
- while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
- file = g_file_get_child (dir, g_file_info_get_name (info));
-
- if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
- if (chown_recursively (file, uid, gid, error) == FALSE) {
- goto out;
- }
- } else if (chown_file (file, uid, gid, error) == FALSE) {
- goto out;
- }
-
- g_clear_object (&file);
- g_clear_object (&info);
- }
-
- if (*error) {
- goto out;
- }
-
- retval = TRUE;
-out:
- g_clear_object (&file);
- g_clear_object (&info);
- g_clear_object (&enumerator);
-
- return retval;
-}
-
GQuark
gdm_display_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_display_error");
}
return ret;
}
time_t
gdm_display_get_creation_time (GdmDisplay *self)
{
g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
return self->priv->creation_time;
}
int
gdm_display_get_status (GdmDisplay *self)
{
g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
return self->priv->status;
}
const char *
gdm_display_get_session_id (GdmDisplay *self)
{
@@ -1649,145 +1577,85 @@ gdm_display_start_greeter_session (GdmDisplay *self)
G_CALLBACK (on_launch_environment_session_stopped),
self, 0);
g_signal_connect_object (self->priv->launch_environment,
"exited",
G_CALLBACK (on_launch_environment_session_exited),
self, 0);
g_signal_connect_object (self->priv->launch_environment,
"died",
G_CALLBACK (on_launch_environment_session_died),
self, 0);
if (auth_file != NULL) {
g_object_set (self->priv->launch_environment,
"x11-authority-file", auth_file,
NULL);
}
gdm_launch_environment_start (self->priv->launch_environment);
session = gdm_launch_environment_get_session (self->priv->launch_environment);
g_object_set (G_OBJECT (session),
"display-is-initial", self->priv->is_initial,
NULL);
g_free (display_name);
g_free (seat_id);
g_free (hostname);
g_free (auth_file);
}
-static void
-chown_initial_setup_home_dir (void)
-{
- GFile *dir;
- GError *error;
- char *gis_dir_path;
- char *gis_uid_path;
- char *gis_uid_contents;
- struct passwd *pwe;
- uid_t uid;
-
- if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
- g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
- return;
- }
-
- gis_dir_path = g_strdup (pwe->pw_dir);
-
- gis_uid_path = g_build_filename (gis_dir_path,
- "gnome-initial-setup-uid",
- NULL);
- if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
- g_warning ("Unable to read %s", gis_uid_path);
- goto out;
- }
-
- uid = (uid_t) atoi (gis_uid_contents);
- pwe = getpwuid (uid);
- if (uid == 0 || pwe == NULL) {
- g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
- goto out;
- }
-
- error = NULL;
- dir = g_file_new_for_path (gis_dir_path);
- if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
- g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
- g_error_free (error);
- }
- g_object_unref (dir);
-out:
- g_free (gis_uid_contents);
- g_free (gis_uid_path);
- g_free (gis_dir_path);
-}
-
void
gdm_display_stop_greeter_session (GdmDisplay *self)
{
GError *error = NULL;
if (self->priv->launch_environment != NULL) {
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
G_CALLBACK (on_launch_environment_session_opened),
self);
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
G_CALLBACK (on_launch_environment_session_started),
self);
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
G_CALLBACK (on_launch_environment_session_stopped),
self);
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
G_CALLBACK (on_launch_environment_session_exited),
self);
g_signal_handlers_disconnect_by_func (self->priv->launch_environment,
G_CALLBACK (on_launch_environment_session_died),
self);
gdm_launch_environment_stop (self->priv->launch_environment);
g_clear_object (&self->priv->launch_environment);
}
-
- if (self->priv->doing_initial_setup) {
- chown_initial_setup_home_dir ();
-
- if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
- "1",
- 1,
- &error)) {
- g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
- ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
- error->message);
- g_clear_error (&error);
- }
- }
}
static xcb_window_t
get_root_window (xcb_connection_t *connection,
int screen_number)
{
xcb_screen_t *screen = NULL;
xcb_screen_iterator_t iter;
iter = xcb_setup_roots_iterator (xcb_get_setup (connection));
while (iter.rem) {
if (screen_number == 0)
screen = iter.data;
screen_number--;
xcb_screen_next (&iter);
}
if (screen != NULL) {
return screen->root;
}
return XCB_WINDOW_NONE;
}
static void
gdm_display_set_windowpath (GdmDisplay *self)
{
/* setting WINDOWPATH for clients */
xcb_intern_atom_cookie_t atom_cookie;
xcb_intern_atom_reply_t *atom_reply = NULL;
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 0823e8638..cf982870c 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -35,60 +35,61 @@
#include <glib-object.h>
#include <act/act-user-manager.h>
#include <systemd/sd-login.h>
#include "gdm-common.h"
#include "gdm-dbus-util.h"
#include "gdm-manager.h"
#include "gdm-manager-glue.h"
#include "gdm-display-store.h"
#include "gdm-display-factory.h"
#include "gdm-launch-environment.h"
#include "gdm-local-display.h"
#include "gdm-local-display-factory.h"
#include "gdm-session.h"
#include "gdm-session-record.h"
#include "gdm-settings-direct.h"
#include "gdm-settings-keys.h"
#include "gdm-xdmcp-display-factory.h"
#include "gdm-xdmcp-chooser-display.h"
#define GDM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_MANAGER, GdmManagerPrivate))
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_MANAGER_PATH GDM_DBUS_PATH "/Manager"
#define GDM_MANAGER_DISPLAYS_PATH GDM_DBUS_PATH "/Displays"
#define INITIAL_SETUP_USERNAME "gnome-initial-setup"
+#define ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT GDM_RUN_DIR "/gdm.ran-initial-setup"
typedef struct
{
GdmManager *manager;
GdmSession *session;
char *service_name;
guint idle_id;
} StartUserSessionOperation;
struct GdmManagerPrivate
{
GdmDisplayStore *display_store;
GdmLocalDisplayFactory *local_factory;
#ifdef HAVE_LIBXDMCP
GdmXdmcpDisplayFactory *xdmcp_factory;
#endif
GdmDisplay *automatic_login_display;
GList *user_sessions;
GHashTable *transient_sessions;
GHashTable *open_reauthentication_requests;
gboolean xdmcp_enabled;
gboolean started;
gboolean show_local_greeter;
GDBusConnection *connection;
GDBusObjectManagerServer *object_manager;
#ifdef WITH_PLYMOUTH
guint plymouth_is_running : 1;
@@ -1630,130 +1631,261 @@ start_user_session (GdmManager *manager,
destroy_start_user_session_operation (operation);
}
static void
create_display_for_user_session (GdmManager *self,
GdmSession *session,
const char *session_id)
{
GdmDisplay *display;
/* at the moment we only create GdmLocalDisplay objects on seat0 */
const char *seat_id = "seat0";
display = gdm_local_display_new ();
g_object_set (G_OBJECT (display),
"session-class", "user",
"seat-id", seat_id,
"session-id", session_id,
NULL);
gdm_display_store_add (self->priv->display_store,
display);
g_object_set_data (G_OBJECT (session), "gdm-display", display);
g_object_set_data_full (G_OBJECT (display),
"gdm-user-session",
g_object_ref (session),
(GDestroyNotify)
clean_user_session);
}
+static gboolean
+chown_file (GFile *file,
+ uid_t uid,
+ gid_t gid,
+ GError **error)
+{
+ if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_UID, uid,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error)) {
+ return FALSE;
+ }
+ if (!g_file_set_attribute_uint32 (file, G_FILE_ATTRIBUTE_UNIX_GID, gid,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error)) {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+chown_recursively (GFile *dir,
+ uid_t uid,
+ gid_t gid,
+ GError **error)
+{
+ GFile *file = NULL;
+ GFileInfo *info = NULL;
+ GFileEnumerator *enumerator = NULL;
+ gboolean retval = FALSE;
+
+ if (chown_file (dir, uid, gid, error) == FALSE) {
+ goto out;
+ }
+
+ enumerator = g_file_enumerate_children (dir,
+ G_FILE_ATTRIBUTE_STANDARD_TYPE","
+ G_FILE_ATTRIBUTE_STANDARD_NAME,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL, error);
+ if (!enumerator) {
+ goto out;
+ }
+
+ while ((info = g_file_enumerator_next_file (enumerator, NULL, error)) != NULL) {
+ file = g_file_get_child (dir, g_file_info_get_name (info));
+
+ if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) {
+ if (chown_recursively (file, uid, gid, error) == FALSE) {
+ goto out;
+ }
+ } else if (chown_file (file, uid, gid, error) == FALSE) {
+ goto out;
+ }
+
+ g_clear_object (&file);
+ g_clear_object (&info);
+ }
+
+ if (*error) {
+ goto out;
+ }
+
+ retval = TRUE;
+out:
+ g_clear_object (&file);
+ g_clear_object (&info);
+ g_clear_object (&enumerator);
+
+ return retval;
+}
+
+static void
+chown_initial_setup_home_dir (void)
+{
+ GFile *dir;
+ GError *error;
+ char *gis_dir_path;
+ char *gis_uid_path;
+ char *gis_uid_contents;
+ struct passwd *pwe;
+ uid_t uid;
+
+ if (!gdm_get_pwent_for_name (INITIAL_SETUP_USERNAME, &pwe)) {
+ g_warning ("Unknown user %s", INITIAL_SETUP_USERNAME);
+ return;
+ }
+
+ gis_dir_path = g_strdup (pwe->pw_dir);
+
+ gis_uid_path = g_build_filename (gis_dir_path,
+ "gnome-initial-setup-uid",
+ NULL);
+ if (!g_file_get_contents (gis_uid_path, &gis_uid_contents, NULL, NULL)) {
+ g_warning ("Unable to read %s", gis_uid_path);
+ goto out;
+ }
+
+ uid = (uid_t) atoi (gis_uid_contents);
+ pwe = getpwuid (uid);
+ if (uid == 0 || pwe == NULL) {
+ g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
+ goto out;
+ }
+
+ error = NULL;
+ dir = g_file_new_for_path (gis_dir_path);
+ if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
+ g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
+ g_error_free (error);
+ }
+ g_object_unref (dir);
+out:
+ g_free (gis_uid_contents);
+ g_free (gis_uid_path);
+ g_free (gis_dir_path);
+}
+
static gboolean
on_start_user_session (StartUserSessionOperation *operation)
{
GdmManager *self = operation->manager;
gboolean migrated;
gboolean fail_if_already_switched = TRUE;
gboolean doing_initial_setup = FALSE;
GdmDisplay *display;
const char *session_id;
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
g_autofree char *display_session_type = NULL;
#endif
g_debug ("GdmManager: start or jump to session");
/* If there's already a session running, jump to it.
* If the only session running is the one we just opened,
* start a session on it.
*/
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
g_debug ("GdmManager: migrated: %d", migrated);
if (migrated) {
/* We don't stop the manager here because
when Xorg exits it switches to the VT it was
started from. That interferes with fast
user switching. */
gdm_session_reset (operation->session);
destroy_start_user_session_operation (operation);
goto out;
}
display = get_display_for_user_session (operation->session);
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
"session-type", &display_session_type,
#endif
NULL);
session_id = gdm_session_get_conversation_session_id (operation->session,
operation->service_name);
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
/* In this case, the greeter's display is morphing into
* the user session display. Kill the greeter on this session
* and let the user session follow the same display. */
gdm_display_stop_greeter_session (display);
g_object_set (G_OBJECT (display),
"session-class", "user",
"session-id", session_id,
NULL);
} else {
uid_t allowed_uid;
g_object_ref (display);
if (doing_initial_setup) {
+ g_autoptr(GError) error = NULL;
+
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
if (g_strcmp0 (display_session_type, "wayland") == 0) {
g_debug ("GdmManager: closing down initial setup display in background");
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
}
#endif
if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
g_debug ("GdmManager: closing down initial setup display");
gdm_display_stop_greeter_session (display);
gdm_display_unmanage (display);
gdm_display_finish (display);
}
+
+ chown_initial_setup_home_dir ();
+
+ if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
+ "1",
+ 1,
+ &error)) {
+ g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
+ ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
+ error->message);
+ g_clear_error (&error);
+ }
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
/* Give the user session a new display object for bookkeeping purposes */
create_display_for_user_session (operation->manager,
operation->session,
session_id);
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
!gdm_session_client_is_connected (operation->session)) {
/* remove the unused prepared greeter display since we're not going
* to have a greeter */
gdm_display_store_remove (self->priv->display_store, display);
g_object_unref (display);
self->priv->automatic_login_display = g_object_get_data (G_OBJECT (operation->session), "gdm-display");
g_object_add_weak_pointer (G_OBJECT (self->priv->automatic_login_display), (gpointer *) &self->priv->automatic_login_display);
}
}
start_user_session (operation->manager, operation);
--
2.27.0

View File

@ -1,117 +0,0 @@
From 49383786d96414e7204ea50ca5ea0263be97b581 Mon Sep 17 00:00:00 2001
From: xiaoguang wang <xwang@suse.com>
Date: Wed, 20 Feb 2019 09:26:02 +0800
Subject: [PATCH 40/51] display-store: make foreach ignore callback return
value
gdm_display_store_foreach is designed to iterate through all
displays in the display store. Under the hood, it currently
uses gdm_display_store_find, though, so will prematurely stop
it's loop if a callback returns TRUE. Callers are getting this
wrong. Some return TRUE with the expectation it goes on, and
some fail to return a value at all.
This commit changes gdm_display_store_foreach to use
g_hash_table_foreach instead, so the callback return values no
longer matter.
---
daemon/gdm-display-store.c | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/daemon/gdm-display-store.c b/daemon/gdm-display-store.c
index fd24334eb..910468cd7 100644
--- a/daemon/gdm-display-store.c
+++ b/daemon/gdm-display-store.c
@@ -119,76 +119,86 @@ remove_display (char *id,
}
gboolean
gdm_display_store_remove (GdmDisplayStore *store,
GdmDisplay *display)
{
g_return_val_if_fail (store != NULL, FALSE);
gdm_display_store_foreach_remove (store,
(GdmDisplayStoreFunc)remove_display,
display);
return FALSE;
}
typedef struct
{
GdmDisplayStoreFunc predicate;
gpointer user_data;
} FindClosure;
static gboolean
find_func (const char *id,
StoredDisplay *stored_display,
FindClosure *closure)
{
return closure->predicate (id,
stored_display->display,
closure->user_data);
}
+static void
+foreach_func (const char *id,
+ StoredDisplay *stored_display,
+ FindClosure *closure)
+{
+ (void) closure->predicate (id,
+ stored_display->display,
+ closure->user_data);
+}
+
void
gdm_display_store_foreach (GdmDisplayStore *store,
GdmDisplayStoreFunc func,
gpointer user_data)
{
FindClosure closure;
g_return_if_fail (store != NULL);
g_return_if_fail (func != NULL);
closure.predicate = func;
closure.user_data = user_data;
- g_hash_table_find (store->priv->displays,
- (GHRFunc) find_func,
- &closure);
+ g_hash_table_foreach (store->priv->displays,
+ (GHFunc) foreach_func,
+ &closure);
}
GdmDisplay *
gdm_display_store_lookup (GdmDisplayStore *store,
const char *id)
{
StoredDisplay *stored_display;
g_return_val_if_fail (store != NULL, NULL);
g_return_val_if_fail (id != NULL, NULL);
stored_display = g_hash_table_lookup (store->priv->displays,
id);
if (stored_display == NULL) {
return NULL;
}
return stored_display->display;
}
GdmDisplay *
gdm_display_store_find (GdmDisplayStore *store,
GdmDisplayStoreFunc predicate,
gpointer user_data)
{
StoredDisplay *stored_display;
FindClosure closure;
g_return_val_if_fail (store != NULL, NULL);
g_return_val_if_fail (predicate != NULL, NULL);
--
2.27.0

View File

@ -1,180 +0,0 @@
From 323358ef61d969588ea048d5b0eba6fd102d3dcf Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 21 Feb 2019 15:20:01 -0500
Subject: [PATCH 41/51] xdmcp-display-factory: don't return value from foreach
funcs
The xdmcp code is returning TRUE from its display store foreach
functions, which is useless since commit 47d01abe and wrong
before that.
This commit makes it return void instead.
---
daemon/gdm-xdmcp-display-factory.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c
index 5b5786c6f..2e14beab4 100644
--- a/daemon/gdm-xdmcp-display-factory.c
+++ b/daemon/gdm-xdmcp-display-factory.c
@@ -639,76 +639,74 @@ gdm_xdmcp_host_allow (GdmAddress *address)
{
#ifdef HAVE_TCPWRAPPERS
char *client;
char *host;
gboolean ret;
host = NULL;
client = NULL;
/* Find client hostname */
gdm_address_get_hostname (address, &client);
gdm_address_get_numeric_info (address, &host, NULL);
/* Check with tcp_wrappers if client is allowed to access */
ret = hosts_ctl ("gdm", client, host, "");
g_free (host);
g_free (client);
return ret;
#else /* HAVE_TCPWRAPPERS */
return (TRUE);
#endif /* HAVE_TCPWRAPPERS */
}
typedef struct {
GdmAddress *address;
int count;
} CountDisplayData;
-static gboolean
+static void
count_displays_from_host (const char *id,
GdmDisplay *display,
CountDisplayData *data)
{
GdmAddress *address;
if (GDM_IS_XDMCP_DISPLAY (display)) {
address = gdm_xdmcp_display_get_remote_address (GDM_XDMCP_DISPLAY (display));
if (gdm_address_equal (address, data->address)) {
data->count++;
}
}
-
- return TRUE;
}
static int
gdm_xdmcp_num_displays_from_host (GdmXdmcpDisplayFactory *factory,
GdmAddress *address)
{
CountDisplayData data;
GdmDisplayStore *store;
data.count = 0;
data.address = address;
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
gdm_display_store_foreach (store,
(GdmDisplayStoreFunc)count_displays_from_host,
&data);
return data.count;
}
typedef struct {
GdmAddress *address;
int display_num;
} LookupHostData;
static gboolean
lookup_by_host (const char *id,
GdmDisplay *display,
LookupHostData *data)
{
@@ -1780,78 +1778,76 @@ gdm_xdmcp_send_managed_forward (GdmXdmcpDisplayFactory *factory,
static void
gdm_xdmcp_send_got_managed_forward (GdmXdmcpDisplayFactory *factory,
GdmAddress *address,
GdmAddress *origin)
{
ARRAY8 addr;
XdmcpHeader header;
char *host;
host = NULL;
gdm_address_get_numeric_info (address, &host, NULL);
g_debug ("GdmXdmcpDisplayFactory: Sending GOT_MANAGED_FORWARD to %s",
host ? host : "(null)");
g_free (host);
set_address_for_request (origin, &addr);
header.opcode = (CARD16) GDM_XDMCP_GOT_MANAGED_FORWARD;
header.length = 4 + addr.length;
header.version = GDM_XDMCP_PROTOCOL_VERSION;
XdmcpWriteHeader (&factory->priv->buf, &header);
XdmcpWriteARRAY8 (&factory->priv->buf, &addr);
XdmcpFlush (factory->priv->socket_fd,
&factory->priv->buf,
(XdmcpNetaddr)gdm_address_peek_sockaddr_storage (address),
(int)gdm_sockaddr_len (gdm_address_peek_sockaddr_storage (address)));
}
-static gboolean
+static void
count_sessions (const char *id,
GdmDisplay *display,
GdmXdmcpDisplayFactory *factory)
{
if (GDM_IS_XDMCP_DISPLAY (display)) {
int status;
status = gdm_display_get_status (display);
if (status == GDM_DISPLAY_MANAGED) {
factory->priv->num_sessions++;
} else if (status == GDM_DISPLAY_UNMANAGED) {
factory->priv->num_pending_sessions++;
}
}
-
- return TRUE;
}
static void
gdm_xdmcp_recount_sessions (GdmXdmcpDisplayFactory *factory)
{
GdmDisplayStore *store;
factory->priv->num_sessions = 0;
factory->priv->num_pending_sessions = 0;
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
gdm_display_store_foreach (store,
(GdmDisplayStoreFunc)count_sessions,
factory);
}
static gboolean
purge_displays (const char *id,
GdmDisplay *display,
GdmXdmcpDisplayFactory *factory)
{
if (GDM_IS_XDMCP_DISPLAY (display)) {
int status;
time_t currtime;
time_t acctime;
currtime = time (NULL);
status = gdm_display_get_status (display);
acctime = gdm_display_get_creation_time (display);
--
2.27.0

View File

@ -1,538 +0,0 @@
From 3cf5b4b12d3d39fa858ff593adeecfe711cdddaf Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
Date: Tue, 7 May 2019 15:35:23 +0100
Subject: [PATCH 42/51] GdmLocalDisplayFactory: Store VT number, not tty
identifier
This makes the code a fair bit simpler.
---
configure.ac | 6 ++--
daemon/gdm-local-display-factory.c | 50 ++++++++++++++++--------------
daemon/gdm-server.c | 2 +-
daemon/gdm-session-worker.c | 2 +-
4 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/configure.ac b/configure.ac
index c549146ce..0c138ab38 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1477,66 +1477,66 @@ fi
AC_SUBST(DEBUG_CFLAGS)
#
# Enable Profiling
#
AC_ARG_ENABLE(profiling,
AS_HELP_STRING([--enable-profiling],
[turn on profiling]),,
enable_profiling=yes)
if test "$enable_profiling" = "yes"; then
AC_DEFINE(ENABLE_PROFILING,1,[enable profiling])
fi
#
# Set SHELL to use in scripts.
#
if test x$os_solaris = xyes ; then
XSESSION_SHELL=/bin/ksh
else
XSESSION_SHELL=/bin/sh
fi
#
# Set VT to use for initial server
#
AC_ARG_WITH(initial-vt,
AS_HELP_STRING([--with-initial-vt=<nr>],
[Initial virtual terminal to use]))
if ! test -z "$with_initial_vt"; then
- GDM_INITIAL_VT="$with_initial_vt"
+ GDM_INITIAL_VT=$with_initial_vt
else
- GDM_INITIAL_VT="1"
+ GDM_INITIAL_VT=1
fi
AC_SUBST(GDM_INITIAL_VT)
-AC_DEFINE_UNQUOTED(GDM_INITIAL_VT, "$GDM_INITIAL_VT", [Initial Virtual Terminal])
+AC_DEFINE_UNQUOTED(GDM_INITIAL_VT, $GDM_INITIAL_VT, [Initial Virtual Terminal])
# Set configuration choices.
#
AC_SUBST(XSESSION_SHELL)
AC_DEFINE_UNQUOTED(XSESSION_SHELL,"$XSESSION_SHELL",[xsession shell])
AC_SUBST(SOUND_PROGRAM)
AC_DEFINE_UNQUOTED(SOUND_PROGRAM,"$SOUND_PROGRAM",[])
AC_SUBST(X_PATH)
AC_SUBST(X_SERVER)
AC_SUBST(X_SERVER_PATH)
AC_DEFINE_UNQUOTED(X_SERVER,"$X_SERVER",[])
AC_DEFINE_UNQUOTED(X_SERVER_PATH,"$X_SERVER_PATH",[])
## Stuff for debian/changelog.in
#if test -e "debian/changelog"; then
# DEBIAN_DATESTAMP=`head -1 debian/changelog| sed -e 's/.*cvs.//' -e 's/).*//'`
# DEBIAN_DATE=`grep '^ --' debian/changelog | head -1 | sed -e 's/.* //'`
#else
# DEBIAN_DATESTAMP=`date +%Y%m%d%H%M%s`
# DEBIAN_DATE=`date -R`
#fi
#
#AC_SUBST(DEBIAN_DATESTAMP)
#AC_SUBST(DEBIAN_DATE)
AC_CONFIG_FILES([
Makefile
pam-extensions/Makefile
pam-extensions/gdm-pam-extensions.pc
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index d999596b5..7a013c694 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -37,61 +37,61 @@
#include "gdm-local-display-factory-glue.h"
#include "gdm-settings-keys.h"
#include "gdm-settings-direct.h"
#include "gdm-display-store.h"
#include "gdm-local-display.h"
#include "gdm-legacy-display.h"
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
#define MAX_DISPLAY_FAILURES 5
#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
struct GdmLocalDisplayFactoryPrivate
{
GdmDBusLocalDisplayFactory *skeleton;
GDBusConnection *connection;
GHashTable *used_display_numbers;
/* FIXME: this needs to be per seat? */
guint num_failures;
guint seat_new_id;
guint seat_removed_id;
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
- char *tty_of_active_vt;
+ unsigned int active_vt;
guint active_vt_watch_id;
guint wait_to_finish_timeout_id;
#endif
};
enum {
PROP_0,
};
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
static void gdm_local_display_factory_finalize (GObject *object);
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
const char *seat_id,
const char *session_type,
gboolean initial_display);
static void on_display_status_changed (GdmDisplay *display,
GParamSpec *arg1,
GdmLocalDisplayFactory *factory);
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
static gpointer local_display_factory_object = NULL;
static gboolean lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data);
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
@@ -641,157 +641,161 @@ maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
return;
}
/* we can only stop greeter for wayland sessions, since
* X server would jump back on exit */
if (g_strcmp0 (display_session_type, "wayland") != 0) {
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
return;
}
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
/* We stop the greeter after a timeout to avoid flicker */
if (factory->priv->wait_to_finish_timeout_id != 0)
g_source_remove (factory->priv->wait_to_finish_timeout_id);
factory->priv->wait_to_finish_timeout_id =
g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
(GSourceFunc)wait_to_finish_timeout,
factory);
}
static gboolean
on_vt_changed (GIOChannel *source,
GIOCondition condition,
GdmLocalDisplayFactory *factory)
{
GIOStatus status;
- static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
- g_autofree char *tty_of_previous_vt = NULL;
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
g_autofree char *active_session_id = NULL;
+ unsigned int previous_vt, new_vt;
const char *session_type = NULL;
- int ret;
+ int ret, n_returned;
g_debug ("GdmLocalDisplayFactory: received VT change event");
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
if (condition & G_IO_PRI) {
g_autoptr (GError) error = NULL;
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
if (error != NULL) {
g_warning ("could not read active VT from kernel: %s", error->message);
}
switch (status) {
case G_IO_STATUS_ERROR:
return G_SOURCE_REMOVE;
case G_IO_STATUS_EOF:
return G_SOURCE_REMOVE;
case G_IO_STATUS_AGAIN:
return G_SOURCE_CONTINUE;
case G_IO_STATUS_NORMAL:
break;
}
}
if ((condition & G_IO_ERR) || (condition & G_IO_HUP)) {
g_debug ("GdmLocalDisplayFactory: kernel hung up active vt watch");
return G_SOURCE_REMOVE;
}
if (tty_of_active_vt == NULL) {
g_debug ("GdmLocalDisplayFactory: unable to read active VT from kernel");
return G_SOURCE_CONTINUE;
}
g_strchomp (tty_of_active_vt);
+ errno = 0;
+ n_returned = sscanf (tty_of_active_vt, "tty%u", &new_vt);
+
+ if (n_returned != 1 || errno != 0) {
+ g_critical ("GdmLocalDisplayFactory: Couldn't read active VT (got '%s')",
+ tty_of_active_vt);
+ return G_SOURCE_CONTINUE;
+ }
+
/* don't do anything if we're on the same VT we were before */
- if (g_strcmp0 (tty_of_active_vt, factory->priv->tty_of_active_vt) == 0) {
+ if (new_vt == factory->priv->active_vt) {
g_debug ("GdmLocalDisplayFactory: VT changed to the same VT, ignoring");
return G_SOURCE_CONTINUE;
}
- tty_of_previous_vt = g_steal_pointer (&factory->priv->tty_of_active_vt);
- factory->priv->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt);
+ previous_vt = factory->priv->active_vt;
+ factory->priv->active_vt = new_vt;
/* don't do anything at start up */
- if (tty_of_previous_vt == NULL) {
- g_debug ("GdmLocalDisplayFactory: VT is %s at startup",
- factory->priv->tty_of_active_vt);
+ if (previous_vt == 0) {
+ g_debug ("GdmLocalDisplayFactory: VT is %u at startup",
+ factory->priv->active_vt);
return G_SOURCE_CONTINUE;
}
- g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
- tty_of_previous_vt, factory->priv->tty_of_active_vt);
+ g_debug ("GdmLocalDisplayFactory: VT changed from %u to %u",
+ previous_vt, factory->priv->active_vt);
/* if the old VT was running a wayland login screen kill it
*/
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
- unsigned int vt;
+ unsigned int login_window_vt;
- ret = sd_session_get_vt (login_session_id, &vt);
- if (ret == 0 && vt != 0) {
- g_autofree char *tty_of_login_window_vt = NULL;
-
- tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
-
- g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
- if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
+ ret = sd_session_get_vt (login_session_id, &login_window_vt);
+ if (ret == 0 && login_window_vt != 0) {
+ g_debug ("GdmLocalDisplayFactory: VT of login window is %u", login_window_vt);
+ if (login_window_vt == previous_vt) {
GdmDisplayStore *store;
GdmDisplay *display;
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
display = gdm_display_store_find (store,
lookup_by_session_id,
(gpointer) login_session_id);
if (display != NULL)
maybe_stop_greeter_in_background (factory, display);
} else {
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
}
}
}
/* if user jumped back to initial vt and it's empty put a login screen
* on it (unless a login screen is already running elsewhere, then
* jump to that login screen)
*/
- if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
+ if (factory->priv->active_vt != GDM_INITIAL_VT) {
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
return G_SOURCE_CONTINUE;
}
if (gdm_local_display_factory_use_wayland ())
session_type = "wayland";
g_debug ("GdmLocalDisplayFactory: creating new display on seat0 because of VT change");
create_display (factory, "seat0", session_type, TRUE);
return G_SOURCE_CONTINUE;
}
#endif
static void
gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
{
g_autoptr (GIOChannel) io_channel = NULL;
factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection,
"org.freedesktop.login1",
"org.freedesktop.login1.Manager",
"SeatNew",
"/org/freedesktop/login1",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
on_seat_new,
g_object_ref (factory),
g_object_unref);
@@ -815,62 +819,60 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
G_IO_PRI,
(GIOFunc)
on_vt_changed,
factory);
}
#endif
}
static void
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
{
if (factory->priv->seat_new_id) {
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
factory->priv->seat_new_id);
factory->priv->seat_new_id = 0;
}
if (factory->priv->seat_removed_id) {
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
factory->priv->seat_removed_id);
factory->priv->seat_removed_id = 0;
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
if (factory->priv->wait_to_finish_timeout_id != 0) {
g_source_remove (factory->priv->wait_to_finish_timeout_id);
factory->priv->wait_to_finish_timeout_id = 0;
}
if (factory->priv->active_vt_watch_id) {
g_source_remove (factory->priv->active_vt_watch_id);
factory->priv->active_vt_watch_id = 0;
}
-
- g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
#endif
}
static void
on_display_added (GdmDisplayStore *display_store,
const char *id,
GdmLocalDisplayFactory *factory)
{
GdmDisplay *display;
display = gdm_display_store_lookup (display_store, id);
if (display != NULL) {
g_signal_connect_object (display, "notify::status",
G_CALLBACK (on_display_status_changed),
factory,
0);
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
}
}
static void
on_display_removed (GdmDisplayStore *display_store,
GdmDisplay *display,
GdmLocalDisplayFactory *factory)
{
g_signal_handlers_disconnect_by_func (display, G_CALLBACK (on_display_status_changed), factory);
g_object_weak_unref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
}
diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
index 83fba99c8..04406a61a 100644
--- a/daemon/gdm-server.c
+++ b/daemon/gdm-server.c
@@ -726,61 +726,61 @@ gdm_server_spawn (GdmServer *server,
(GChildWatchFunc)server_child_watch,
server);
ret = TRUE;
out:
g_strfreev (argv);
if (env) {
g_ptr_array_foreach (env, (GFunc)g_free, NULL);
g_ptr_array_free (env, TRUE);
}
return ret;
}
/**
* gdm_server_start:
* @disp: Pointer to a GdmDisplay structure
*
* Starts a local X server. Handles retries and fatal errors properly.
*/
gboolean
gdm_server_start (GdmServer *server)
{
gboolean res = FALSE;
const char *vtarg = NULL;
GError *local_error = NULL;
GError **error = &local_error;
/* Hardcode the VT for the initial X server, but nothing else */
if (server->priv->is_initial) {
- vtarg = "vt" GDM_INITIAL_VT;
+ vtarg = "vt" G_STRINGIFY (GDM_INITIAL_VT);
}
/* fork X server process */
if (!gdm_server_spawn (server, vtarg, error)) {
goto out;
}
res = TRUE;
out:
if (local_error) {
g_printerr ("%s\n", local_error->message);
g_clear_error (&local_error);
}
return res;
}
static void
server_died (GdmServer *server)
{
int exit_status;
g_debug ("GdmServer: Waiting on process %d", server->priv->pid);
exit_status = gdm_wait_on_pid (server->priv->pid);
if (WIFEXITED (exit_status) && (WEXITSTATUS (exit_status) != 0)) {
g_debug ("GdmServer: Wait on child process failed");
} else {
/* exited normally */
}
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 7ed2789da..b4befaa83 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -2202,61 +2202,61 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
g_debug ("GdmSessionWorker: state SESSION_STARTED");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
gdm_session_worker_watch_child (worker);
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static gboolean
set_up_for_new_vt (GdmSessionWorker *worker)
{
int fd;
char vt_string[256], tty_string[256];
int session_vt = 0;
fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
if (fd < 0) {
g_debug ("GdmSessionWorker: couldn't open VT master: %m");
return FALSE;
}
if (worker->priv->display_is_initial) {
- session_vt = atoi (GDM_INITIAL_VT);
+ session_vt = GDM_INITIAL_VT;
} else {
if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
g_debug ("GdmSessionWorker: couldn't open new VT: %m");
goto fail;
}
}
worker->priv->session_vt = session_vt;
close (fd);
fd = -1;
g_assert (session_vt > 0);
g_snprintf (vt_string, sizeof (vt_string), "%d", session_vt);
/* Set the VTNR. This is used by logind to configure a session in
* the logind-managed case, but it doesn't hurt to set it always.
* When logind gains support for XDG_VTNR=auto, we can make the
* OPENQRY and this whole path only used by the new VT code. */
gdm_session_worker_set_environment_variable (worker,
"XDG_VTNR",
vt_string);
g_snprintf (tty_string, 256, "/dev/tty%d", session_vt);
worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
return TRUE;
--
2.27.0

View File

@ -1,344 +0,0 @@
From 476230f7b721781c682d26983c9a2fd82afc45e1 Mon Sep 17 00:00:00 2001
From: Benjamin Berg <bberg@redhat.com>
Date: Wed, 25 Sep 2019 14:51:40 +0200
Subject: [PATCH 43/51] gdm-session-worker: Drop login_vt assuming it is
GDM_INITIAL_VT
When a session ends, its "session worker" is closed. Since
3e8220921bb608afd06ed677104fd2244b901a28 (3.33.4), we uninitialise PAM
when this happens. As part of this procedure, we jump back to the login
screen, if the screen being killed is not itself the login screen.
This has broken fast user switching. It goes like this - this
explanation is a bit complicated, bear with us:
We want to jump back to the login screen when a normal user session
ends, so that people can log in again. We do not want to do this when a
login screen itself ends. When session workers start up, they query for
the *currently active VT* and save this in `login_vt`. Then later on, we
check if our session ID is the same as `login_vt`, and jump to
`login_vt` if they are different - this means that it was a user session
not a login session. Querying the currently active VT is fine for the
first greeter, but when initiating a user switch it's wrong as this
gives the user VT.
GDM greeters are killed once they have spawned a session. They are
associated with a logind session, and therefore a PAM session. There are
some actions performed when unregistering PAM sessions, including the
previously mentioned VT jump. Before
3e8220921bb608afd06ed677104fd2244b901a28 we only uninitialised PAM when
the session itself exited so the bug was masked, but now (since this
commit), if the login screen's *worker* exits first - as happens in the
normal case when GDM kills it - we also do this uninitialisation. Since
we falsely recorded the login screen as the first user's VT, this means
that checking `login_vt != session_vt` returns `TRUE` and we jump back
to the previous user's session immediately after logging into the new
session: fast user switching is broken.
Since the work on shutting down the GDM session has been finished, we
can assume that the login_vt is always on GDM_INITIAL_VT (see
example c71bc5d6c3bc2ec448b5c72ce9a811d9c0c7905e
"local-display-factory: Remove initial VT is in use check" and
39fb4ff64e6a0653e70a3bfab31da47b49227d59 "manager: don't run autologin
display on tty1"). So simply replace all usages of login_vt with
GDM_INITIAL_VT to solve the above problem.
Note that in the case where ENABLE_USER_DISPLAY_SERVER is not enabled,
the login_vt is always the same as the session_vt. We can simply remove
the VT switching magic there and everything should be working as
expected.
This is a simpler version of the patch by Iain Lane <iainl@gnome.org>,
taking into account that we can make the assumption about the login_vt.
Closes #515
---
daemon/gdm-session-worker.c | 43 +++++++++----------------------------
1 file changed, 10 insertions(+), 33 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index b4befaa83..0bd78cfaf 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -119,61 +119,60 @@ typedef struct
} ReauthenticationRequest;
struct GdmSessionWorkerPrivate
{
GdmSessionWorkerState state;
int exit_code;
pam_handle_t *pam_handle;
GPid child_pid;
guint child_watch_id;
/* from Setup */
char *service;
char *x11_display_name;
char *x11_authority_file;
char *display_device;
char *display_seat_id;
char *hostname;
char *username;
char *log_file;
char *session_id;
uid_t uid;
gid_t gid;
gboolean password_is_required;
char **extensions;
int cred_flags;
- int login_vt;
int session_vt;
int session_tty_fd;
char **arguments;
guint32 cancelled : 1;
guint32 timed_out : 1;
guint32 is_program_session : 1;
guint32 is_reauth_session : 1;
guint32 display_is_local : 1;
guint32 display_is_initial : 1;
guint state_change_idle_id;
GdmSessionDisplayMode display_mode;
char *server_address;
GDBusConnection *connection;
GdmDBusWorkerManager *manager;
GHashTable *reauthentication_requests;
GdmSessionAuditor *auditor;
GdmSessionSettings *user_settings;
GDBusMethodInvocation *pending_invocation;
};
#ifdef SUPPORTS_PAM_EXTENSIONS
static char gdm_pam_extension_environment_block[_POSIX_ARG_MAX];
static const char * const
gdm_supported_pam_extensions[] = {
@@ -1029,141 +1028,120 @@ gdm_session_worker_set_state (GdmSessionWorker *worker,
static void
gdm_session_worker_uninitialize_pam (GdmSessionWorker *worker,
int status)
{
g_debug ("GdmSessionWorker: uninitializing PAM");
if (worker->priv->pam_handle == NULL)
return;
gdm_session_worker_get_username (worker, NULL);
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_SESSION_OPENED) {
pam_close_session (worker->priv->pam_handle, 0);
gdm_session_auditor_report_logout (worker->priv->auditor);
} else {
gdm_session_auditor_report_login_failure (worker->priv->auditor,
status,
pam_strerror (worker->priv->pam_handle, status));
}
if (worker->priv->state >= GDM_SESSION_WORKER_STATE_ACCREDITED) {
pam_setcred (worker->priv->pam_handle, PAM_DELETE_CRED);
}
pam_end (worker->priv->pam_handle, status);
worker->priv->pam_handle = NULL;
gdm_session_worker_stop_auditor (worker);
+ /* If user-display-server is not enabled the login_vt is always
+ * identical to the session_vt. So in that case we never need to
+ * do a VT switch. */
+#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (worker->priv->display_seat_id, "seat0") == 0) {
- if (worker->priv->login_vt != worker->priv->session_vt) {
- jump_to_vt (worker, worker->priv->login_vt);
+ /* Switch to the login VT if we are not the login screen. */
+ if (worker->priv->session_vt != GDM_INITIAL_VT) {
+ jump_to_vt (worker, GDM_INITIAL_VT);
}
}
+#endif
- worker->priv->login_vt = 0;
worker->priv->session_vt = 0;
g_debug ("GdmSessionWorker: state NONE");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_NONE);
}
static char *
_get_tty_for_pam (const char *x11_display_name,
const char *display_device)
{
#ifdef __sun
return g_strdup (display_device);
#else
return g_strdup (x11_display_name);
#endif
}
#ifdef PAM_XAUTHDATA
static struct pam_xauth_data *
_get_xauth_for_pam (const char *x11_authority_file)
{
FILE *fh;
Xauth *auth = NULL;
struct pam_xauth_data *retval = NULL;
gsize len = sizeof (*retval) + 1;
fh = fopen (x11_authority_file, "r");
if (fh) {
auth = XauReadAuth (fh);
fclose (fh);
}
if (auth) {
len += auth->name_length + auth->data_length;
retval = g_malloc0 (len);
}
if (retval) {
retval->namelen = auth->name_length;
retval->name = (char *) (retval + 1);
memcpy (retval->name, auth->name, auth->name_length);
retval->datalen = auth->data_length;
retval->data = retval->name + auth->name_length + 1;
memcpy (retval->data, auth->data, auth->data_length);
}
XauDisposeAuth (auth);
return retval;
}
#endif
-static gboolean
-ensure_login_vt (GdmSessionWorker *worker)
-{
- int fd;
- struct vt_stat vt_state = { 0 };
- gboolean got_login_vt = FALSE;
-
- fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
-
- if (fd < 0) {
- g_debug ("GdmSessionWorker: couldn't open VT master: %m");
- return FALSE;
- }
-
- if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
- g_debug ("GdmSessionWorker: couldn't get current VT: %m");
- goto out;
- }
-
- worker->priv->login_vt = vt_state.v_active;
- got_login_vt = TRUE;
-out:
- close (fd);
- return got_login_vt;
-}
-
static gboolean
gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
const char *service,
const char * const *extensions,
const char *username,
const char *hostname,
gboolean display_is_local,
const char *x11_display_name,
const char *x11_authority_file,
const char *display_device,
const char *seat_id,
GError **error)
{
struct pam_conv pam_conversation;
int error_code;
char tty_string[256];
g_assert (worker->priv->pam_handle == NULL);
g_debug ("GdmSessionWorker: initializing PAM; service=%s username=%s seat=%s",
service ? service : "(null)",
username ? username : "(null)",
seat_id ? seat_id : "(null)");
#ifdef SUPPORTS_PAM_EXTENSIONS
if (extensions != NULL) {
GDM_PAM_EXTENSION_ADVERTISE_SUPPORTED_EXTENSIONS (gdm_pam_extension_environment_block, extensions);
}
#endif
@@ -1204,64 +1182,63 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
}
/* set RHOST */
if (hostname != NULL && hostname[0] != '\0') {
error_code = pam_set_item (worker->priv->pam_handle, PAM_RHOST, hostname);
g_debug ("error informing authentication system of user's hostname %s: %s",
hostname,
pam_strerror (worker->priv->pam_handle, error_code));
if (error_code != PAM_SUCCESS) {
g_set_error (error,
GDM_SESSION_WORKER_ERROR,
GDM_SESSION_WORKER_ERROR_AUTHENTICATING,
"%s", "");
goto out;
}
}
/* set seat ID */
if (seat_id != NULL && seat_id[0] != '\0') {
gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
}
if (strcmp (service, "gdm-launch-environment") == 0) {
gdm_session_worker_set_environment_variable (worker, "XDG_SESSION_CLASS", "greeter");
}
g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
- /* Temporarily set PAM_TTY with the currently active VT (login screen)
+ /* Temporarily set PAM_TTY with the login VT,
PAM_TTY will be reset with the users VT right before the user session is opened */
- ensure_login_vt (worker);
- g_snprintf (tty_string, 256, "/dev/tty%d", worker->priv->login_vt);
+ g_snprintf (tty_string, 256, "/dev/tty%d", GDM_INITIAL_VT);
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
if (!display_is_local)
worker->priv->password_is_required = TRUE;
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static gboolean
gdm_session_worker_authenticate_user (GdmSessionWorker *worker,
gboolean password_is_required,
GError **error)
{
int error_code;
int authentication_flags;
g_debug ("GdmSessionWorker: authenticating user %s", worker->priv->username);
authentication_flags = 0;
if (password_is_required) {
authentication_flags |= PAM_DISALLOW_NULL_AUTHTOK;
}
/* blocking call, does the actual conversation */
--
2.27.0

View File

@ -1,160 +0,0 @@
From 75b65846ca77bd2d42e25365b4b7242a406330cf Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 7 Apr 2020 14:37:41 -0400
Subject: [PATCH 44/51] session-worker: ensure initial vt is never picked for
!is_initial displays
Normally, a !is_initial display would never "get" tty1, since the system
boots to tty1. But if, for some reason, the user booted to runlevel 3,
then switched to runlevel 5, the login screen could get started when
tty1 is free.
That means, e.g., an autologin user can end up getting allocated tty1,
which is bad, since we assume tty1 is used for the login screen.
This commit opens up /dev/tty1 when querying for available VTs, so that
it never gets returned by the kernel as available.
---
daemon/gdm-session-worker.c | 39 +++++++++++++++++++++++++------------
1 file changed, 27 insertions(+), 12 deletions(-)
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 0bd78cfaf..42c415837 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -2167,105 +2167,120 @@ gdm_session_worker_start_session (GdmSessionWorker *worker,
/* If we end up execing again, make sure we don't use the executable context set up
* by pam_selinux durin pam_open_session
*/
#ifdef HAVE_SELINUX
setexeccon (NULL);
#endif
worker->priv->child_pid = session_pid;
g_debug ("GdmSessionWorker: session opened creating reply...");
g_assert (sizeof (GPid) <= sizeof (int));
g_debug ("GdmSessionWorker: state SESSION_STARTED");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SESSION_STARTED);
gdm_session_worker_watch_child (worker);
out:
if (error_code != PAM_SUCCESS) {
gdm_session_worker_uninitialize_pam (worker, error_code);
return FALSE;
}
return TRUE;
}
static gboolean
set_up_for_new_vt (GdmSessionWorker *worker)
{
- int fd;
+ int initial_vt_fd;
char vt_string[256], tty_string[256];
int session_vt = 0;
- fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
-
- if (fd < 0) {
- g_debug ("GdmSessionWorker: couldn't open VT master: %m");
+ /* open the initial vt. We need it for two scenarios:
+ *
+ * 1) display_is_initial is TRUE. We need it directly.
+ * 2) display_is_initial is FALSE. We need it to mark
+ * the initial VT as "in use" so it doesn't get returned
+ * by VT_OPENQRY
+ * */
+ g_snprintf (tty_string, sizeof (tty_string), "/dev/tty%d", GDM_INITIAL_VT);
+ initial_vt_fd = open (tty_string, O_RDWR | O_NOCTTY);
+
+ if (initial_vt_fd < 0) {
+ g_debug ("GdmSessionWorker: couldn't open console of initial fd: %m");
return FALSE;
}
if (worker->priv->display_is_initial) {
session_vt = GDM_INITIAL_VT;
} else {
- if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) {
+
+ /* Typically VT_OPENQRY is called on /dev/tty0, but we already
+ * have /dev/tty1 open above, so might as well use it.
+ */
+ if (ioctl (initial_vt_fd, VT_OPENQRY, &session_vt) < 0) {
g_debug ("GdmSessionWorker: couldn't open new VT: %m");
goto fail;
}
}
worker->priv->session_vt = session_vt;
- close (fd);
- fd = -1;
-
g_assert (session_vt > 0);
g_snprintf (vt_string, sizeof (vt_string), "%d", session_vt);
/* Set the VTNR. This is used by logind to configure a session in
* the logind-managed case, but it doesn't hurt to set it always.
* When logind gains support for XDG_VTNR=auto, we can make the
* OPENQRY and this whole path only used by the new VT code. */
gdm_session_worker_set_environment_variable (worker,
"XDG_VTNR",
vt_string);
- g_snprintf (tty_string, 256, "/dev/tty%d", session_vt);
- worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
+ if (worker->priv->display_is_initial) {
+ worker->priv->session_tty_fd = initial_vt_fd;
+ } else {
+ g_snprintf (tty_string, sizeof (tty_string), "/dev/tty%d", session_vt);
+ worker->priv->session_tty_fd = open (tty_string, O_RDWR | O_NOCTTY);
+ close (initial_vt_fd);
+ }
+
pam_set_item (worker->priv->pam_handle, PAM_TTY, tty_string);
return TRUE;
fail:
- close (fd);
+ close (initial_vt_fd);
return FALSE;
}
static gboolean
set_xdg_vtnr_to_current_vt (GdmSessionWorker *worker)
{
int fd;
char vt_string[256];
struct vt_stat vt_state = { 0 };
fd = open ("/dev/tty0", O_RDWR | O_NOCTTY);
if (fd < 0) {
g_debug ("GdmSessionWorker: couldn't open VT master: %m");
return FALSE;
}
if (ioctl (fd, VT_GETSTATE, &vt_state) < 0) {
g_debug ("GdmSessionWorker: couldn't get current VT: %m");
goto fail;
}
close (fd);
fd = -1;
g_snprintf (vt_string, sizeof (vt_string), "%d", vt_state.v_active);
gdm_session_worker_set_environment_variable (worker,
"XDG_VTNR",
vt_string);
--
2.27.0

View File

@ -1,114 +0,0 @@
From fc3503f16e9de535d2a36b904720b360370f880f Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 15 May 2020 10:08:24 -0400
Subject: [PATCH 45/51] local-display-factory: Always force login screen to VT
1
These days we always want the login screen on VT 1, even
when it's created by user switching.
Unfortunately, since commit f843233ad the login screen
won't naturally pick VT 1 when user switching.
This commit forces it to make the right choice.
Closes https://gitlab.gnome.org/GNOME/gdm/-/issues/602
---
daemon/gdm-local-display-factory.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 7a013c694..a288f8765 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -197,84 +197,87 @@ store_display (GdmLocalDisplayFactory *factory,
gdm_display_store_add (store, display);
}
static gboolean
gdm_local_display_factory_use_wayland (void)
{
#ifdef ENABLE_WAYLAND_SUPPORT
gboolean wayland_enabled = FALSE;
if (gdm_settings_direct_get_boolean (GDM_KEY_WAYLAND_ENABLE, &wayland_enabled)) {
if (wayland_enabled && g_file_test ("/usr/bin/Xwayland", G_FILE_TEST_IS_EXECUTABLE) )
return TRUE;
}
#endif
return FALSE;
}
/*
Example:
dbus-send --system --dest=org.gnome.DisplayManager \
--type=method_call --print-reply --reply-timeout=2000 \
/org/gnome/DisplayManager/Manager \
org.gnome.DisplayManager.Manager.GetDisplays
*/
gboolean
gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *factory,
char **id,
GError **error)
{
gboolean ret;
GdmDisplay *display = NULL;
+ gboolean is_initial = FALSE;
g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
ret = FALSE;
g_debug ("GdmLocalDisplayFactory: Creating transient display");
#ifdef ENABLE_USER_DISPLAY_SERVER
display = gdm_local_display_new ();
if (gdm_local_display_factory_use_wayland ())
g_object_set (G_OBJECT (display), "session-type", "wayland", NULL);
+ is_initial = TRUE;
#else
if (display == NULL) {
guint32 num;
num = take_next_display_number (factory);
display = gdm_legacy_display_new (num);
}
#endif
g_object_set (display,
"seat-id", "seat0",
"allow-timed-login", FALSE,
+ "is-initial", is_initial,
NULL);
store_display (factory, display);
if (! gdm_display_manage (display)) {
display = NULL;
goto out;
}
if (! gdm_display_get_id (display, id, NULL)) {
display = NULL;
goto out;
}
ret = TRUE;
out:
/* ref either held by store or not at all */
g_object_unref (display);
return ret;
}
static gboolean
finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
GdmDisplay *display,
const char *seat_id)
{
if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
return FALSE;
--
2.27.0

View File

@ -1,81 +0,0 @@
From 763e31a576a4cd665e5ad06ad0eb4610cecc0b42 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Fri, 10 Jul 2020 10:45:52 -0400
Subject: [PATCH 46/51] gdm-x-session: tell x server to not vt switch
gdm already handles the VT switching on X's behalf,
so it's redundant, and X does it at inopportune times,
so instruct it to not get involved.
---
daemon/gdm-x-session.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 3b2fcef47..d8e3c7d53 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -247,60 +247,61 @@ spawn_x_server (State *state,
}
g_ptr_array_add (arguments, "-displayfd");
g_ptr_array_add (arguments, display_fd_string);
g_ptr_array_add (arguments, "-auth");
g_ptr_array_add (arguments, auth_file);
/* If we were compiled with Xserver >= 1.17 we need to specify
* '-listen tcp' as the X server dosen't listen on tcp sockets
* by default anymore. In older versions we need to pass
* -nolisten tcp to disable listening on tcp sockets.
*/
#ifdef HAVE_XSERVER_THAT_DEFAULTS_TO_LOCAL_ONLY
if (allow_remote_connections) {
g_ptr_array_add (arguments, "-listen");
g_ptr_array_add (arguments, "tcp");
}
#else
if (!allow_remote_connections) {
g_ptr_array_add (arguments, "-nolisten");
g_ptr_array_add (arguments, "tcp");
}
#endif
g_ptr_array_add (arguments, "-background");
g_ptr_array_add (arguments, "none");
g_ptr_array_add (arguments, "-noreset");
g_ptr_array_add (arguments, "-keeptty");
+ g_ptr_array_add (arguments, "-novtswitch");
g_ptr_array_add (arguments, "-verbose");
if (state->debug_enabled) {
g_ptr_array_add (arguments, "7");
} else {
g_ptr_array_add (arguments, "3");
}
if (state->debug_enabled) {
g_ptr_array_add (arguments, "-core");
}
g_ptr_array_add (arguments, NULL);
subprocess = g_subprocess_launcher_spawnv (launcher,
(const char * const *) arguments->pdata,
&error);
g_free (display_fd_string);
g_clear_object (&launcher);
g_ptr_array_free (arguments, TRUE);
if (subprocess == NULL) {
g_debug ("could not start X server: %s", error->message);
goto out;
}
input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
data_stream = g_data_input_stream_new (input_stream);
g_clear_object (&input_stream);
display_number = g_data_input_stream_read_line (data_stream,
--
2.27.0

View File

@ -1,115 +0,0 @@
From a1c74e2e42dea464ab0b439b767da5c12cbf3986 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 11 Oct 2018 07:15:56 -0400
Subject: [PATCH 47/51] local-display-factory: kill X on login just like
wayland
These days we kill the wayland login screen during login to
conserve system resources.
We've been reluctant to do the same for X based login screens,
because X didn't handle being killed in the background so well.
This is no longer a problem, since this commit:
https://gitlab.freedesktop.org/xorg/xserver/-/commit/ff91c696ff8f5f56da40e107cb5c321539758a81
So let's go ahead and kill it now.
---
daemon/gdm-local-display-factory.c | 9 ---------
1 file changed, 9 deletions(-)
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index a288f8765..aae226750 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -599,86 +599,77 @@ on_seat_removed (GDBusConnection *connection,
g_variant_get (parameters, "(&s&o)", &seat, NULL);
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
}
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
static gboolean
lookup_by_session_id (const char *id,
GdmDisplay *display,
gpointer user_data)
{
const char *looking_for = user_data;
const char *current;
current = gdm_display_get_session_id (display);
return g_strcmp0 (current, looking_for) == 0;
}
static gboolean
wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
{
finish_waiting_displays_on_seat (factory, "seat0");
factory->priv->wait_to_finish_timeout_id = 0;
return G_SOURCE_REMOVE;
}
static void
maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
GdmDisplay *display)
{
- g_autofree char *display_session_type = NULL;
gboolean doing_initial_setup = FALSE;
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
return;
}
g_object_get (G_OBJECT (display),
- "session-type", &display_session_type,
"doing-initial-setup", &doing_initial_setup,
NULL);
/* we don't ever stop initial-setup implicitly */
if (doing_initial_setup) {
g_debug ("GdmLocalDisplayFactory: login window is performing initial-setup, so ignoring");
return;
}
- /* we can only stop greeter for wayland sessions, since
- * X server would jump back on exit */
- if (g_strcmp0 (display_session_type, "wayland") != 0) {
- g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
- return;
- }
-
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
/* We stop the greeter after a timeout to avoid flicker */
if (factory->priv->wait_to_finish_timeout_id != 0)
g_source_remove (factory->priv->wait_to_finish_timeout_id);
factory->priv->wait_to_finish_timeout_id =
g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
(GSourceFunc)wait_to_finish_timeout,
factory);
}
static gboolean
on_vt_changed (GIOChannel *source,
GIOCondition condition,
GdmLocalDisplayFactory *factory)
{
GIOStatus status;
g_autofree char *tty_of_active_vt = NULL;
g_autofree char *login_session_id = NULL;
g_autofree char *active_session_id = NULL;
unsigned int previous_vt, new_vt;
const char *session_type = NULL;
int ret, n_returned;
g_debug ("GdmLocalDisplayFactory: received VT change event");
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
if (condition & G_IO_PRI) {
--
2.27.0

View File

@ -1,149 +0,0 @@
From f1b7d85b46dfc253176d6a043dcce26da3a26dfb Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Mon, 13 Jul 2020 09:23:06 -0400
Subject: [PATCH 48/51] manager: don't kill initial-setup right away with Xorg
either
The login screen for both Xorg and wayland sessions is now silently
killed in the background post login.
We still kill initial-setup for Xorg sessions up front, though.
This commit fixes that.
---
daemon/gdm-manager.c | 20 ++------------------
1 file changed, 2 insertions(+), 18 deletions(-)
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index cf982870c..b147d73db 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1757,123 +1757,107 @@ chown_initial_setup_home_dir (void)
uid = (uid_t) atoi (gis_uid_contents);
pwe = getpwuid (uid);
if (uid == 0 || pwe == NULL) {
g_warning ("UID '%s' in %s is not valid", gis_uid_contents, gis_uid_path);
goto out;
}
error = NULL;
dir = g_file_new_for_path (gis_dir_path);
if (!chown_recursively (dir, pwe->pw_uid, pwe->pw_gid, &error)) {
g_warning ("Failed to change ownership for %s: %s", gis_dir_path, error->message);
g_error_free (error);
}
g_object_unref (dir);
out:
g_free (gis_uid_contents);
g_free (gis_uid_path);
g_free (gis_dir_path);
}
static gboolean
on_start_user_session (StartUserSessionOperation *operation)
{
GdmManager *self = operation->manager;
gboolean migrated;
gboolean fail_if_already_switched = TRUE;
gboolean doing_initial_setup = FALSE;
GdmDisplay *display;
const char *session_id;
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
- g_autofree char *display_session_type = NULL;
-#endif
g_debug ("GdmManager: start or jump to session");
/* If there's already a session running, jump to it.
* If the only session running is the one we just opened,
* start a session on it.
*/
migrated = switch_to_compatible_user_session (operation->manager, operation->session, fail_if_already_switched);
g_debug ("GdmManager: migrated: %d", migrated);
if (migrated) {
/* We don't stop the manager here because
when Xorg exits it switches to the VT it was
started from. That interferes with fast
user switching. */
gdm_session_reset (operation->session);
destroy_start_user_session_operation (operation);
goto out;
}
display = get_display_for_user_session (operation->session);
g_object_get (G_OBJECT (display),
"doing-initial-setup", &doing_initial_setup,
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
- "session-type", &display_session_type,
-#endif
NULL);
session_id = gdm_session_get_conversation_session_id (operation->session,
operation->service_name);
if (gdm_session_get_display_mode (operation->session) == GDM_SESSION_DISPLAY_MODE_REUSE_VT) {
/* In this case, the greeter's display is morphing into
* the user session display. Kill the greeter on this session
* and let the user session follow the same display. */
gdm_display_stop_greeter_session (display);
g_object_set (G_OBJECT (display),
"session-class", "user",
"session-id", session_id,
NULL);
} else {
uid_t allowed_uid;
g_object_ref (display);
if (doing_initial_setup) {
g_autoptr(GError) error = NULL;
-#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
- if (g_strcmp0 (display_session_type, "wayland") == 0) {
- g_debug ("GdmManager: closing down initial setup display in background");
- g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
- }
-#endif
- if (gdm_display_get_status (display) == GDM_DISPLAY_MANAGED) {
- g_debug ("GdmManager: closing down initial setup display");
- gdm_display_stop_greeter_session (display);
- gdm_display_unmanage (display);
- gdm_display_finish (display);
- }
+ g_debug ("GdmManager: closing down initial setup display in background");
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
chown_initial_setup_home_dir ();
if (!g_file_set_contents (ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
"1",
1,
&error)) {
g_warning ("GdmDisplay: Could not write initial-setup-done marker to %s: %s",
ALREADY_RAN_INITIAL_SETUP_ON_THIS_BOOT,
error->message);
g_clear_error (&error);
}
} else {
g_debug ("GdmManager: session has its display server, reusing our server for another login screen");
}
/* The user session is going to follow the session worker
* into the new display. Untie it from this display and
* create a new session for a future user login. */
allowed_uid = gdm_session_get_allowed_user (operation->session);
g_object_set_data (G_OBJECT (display), "gdm-user-session", NULL);
g_object_set_data (G_OBJECT (operation->session), "gdm-display", NULL);
create_user_session_for_display (operation->manager, display, allowed_uid);
/* Give the user session a new display object for bookkeeping purposes */
create_display_for_user_session (operation->manager,
operation->session,
session_id);
if ((g_strcmp0 (operation->service_name, "gdm-autologin") == 0) &&
--
2.27.0

View File

@ -1,551 +0,0 @@
From 2724b4fd6d4ac527acc481f056f535141b63fe24 Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
Date: Tue, 7 May 2019 15:57:43 +0100
Subject: [PATCH 49/51] GdmManager, GdmDisplay: Add RegisterSession method
Window managers can use this to register with GDM when they've finished
starting up and started displaying.
---
daemon/gdm-display.c | 24 ++++++++++++++++++++++++
daemon/gdm-manager.c | 30 ++++++++++++++++++++++++++++++
daemon/gdm-manager.xml | 3 +++
3 files changed, 57 insertions(+)
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index 1cef8c7c1..56799741d 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -64,82 +64,84 @@ struct GdmDisplayPrivate
char *remote_hostname;
int x11_display_number;
char *x11_display_name;
int status;
time_t creation_time;
GTimer *server_timer;
char *x11_cookie;
gsize x11_cookie_size;
GdmDisplayAccessFile *access_file;
guint finish_idle_id;
xcb_connection_t *xcb_connection;
int xcb_screen_number;
GDBusConnection *connection;
GdmDisplayAccessFile *user_access_file;
GdmDBusDisplay *display_skeleton;
GDBusObjectSkeleton *object_skeleton;
/* this spawns and controls the greeter session */
GdmLaunchEnvironment *launch_environment;
guint is_local : 1;
guint is_initial : 1;
guint allow_timed_login : 1;
guint have_existing_user_accounts : 1;
guint doing_initial_setup : 1;
+ guint session_registered : 1;
};
enum {
PROP_0,
PROP_ID,
PROP_STATUS,
PROP_SEAT_ID,
PROP_SESSION_ID,
PROP_SESSION_CLASS,
PROP_SESSION_TYPE,
PROP_REMOTE_HOSTNAME,
PROP_X11_DISPLAY_NUMBER,
PROP_X11_DISPLAY_NAME,
PROP_X11_COOKIE,
PROP_X11_AUTHORITY_FILE,
PROP_IS_CONNECTED,
PROP_IS_LOCAL,
PROP_LAUNCH_ENVIRONMENT,
PROP_IS_INITIAL,
PROP_ALLOW_TIMED_LOGIN,
PROP_HAVE_EXISTING_USER_ACCOUNTS,
PROP_DOING_INITIAL_SETUP,
+ PROP_SESSION_REGISTERED,
};
static void gdm_display_class_init (GdmDisplayClass *klass);
static void gdm_display_init (GdmDisplay *self);
static void gdm_display_finalize (GObject *object);
static void queue_finish (GdmDisplay *self);
static void _gdm_display_set_status (GdmDisplay *self,
int status);
static gboolean wants_initial_setup (GdmDisplay *self);
G_DEFINE_ABSTRACT_TYPE (GdmDisplay, gdm_display, G_TYPE_OBJECT)
GQuark
gdm_display_error_quark (void)
{
static GQuark ret = 0;
if (ret == 0) {
ret = g_quark_from_static_string ("gdm_display_error");
}
return ret;
}
time_t
gdm_display_get_creation_time (GdmDisplay *self)
{
g_return_val_if_fail (GDM_IS_DISPLAY (self), 0);
return self->priv->creation_time;
}
@@ -733,60 +735,68 @@ static void
_gdm_display_set_x11_display_number (GdmDisplay *self,
int num)
{
self->priv->x11_display_number = num;
}
static void
_gdm_display_set_x11_display_name (GdmDisplay *self,
const char *x11_display)
{
g_free (self->priv->x11_display_name);
self->priv->x11_display_name = g_strdup (x11_display);
}
static void
_gdm_display_set_x11_cookie (GdmDisplay *self,
const char *x11_cookie)
{
g_free (self->priv->x11_cookie);
self->priv->x11_cookie = g_strdup (x11_cookie);
}
static void
_gdm_display_set_is_local (GdmDisplay *self,
gboolean is_local)
{
g_debug ("GdmDisplay: local: %s", is_local? "yes" : "no");
self->priv->is_local = is_local;
}
+static void
+_gdm_display_set_session_registered (GdmDisplay *self,
+ gboolean registered)
+{
+ g_debug ("GdmDisplay: session registered: %s", registered? "yes" : "no");
+ self->priv->session_registered = registered;
+}
+
static void
_gdm_display_set_launch_environment (GdmDisplay *self,
GdmLaunchEnvironment *launch_environment)
{
g_clear_object (&self->priv->launch_environment);
self->priv->launch_environment = g_object_ref (launch_environment);
}
static void
_gdm_display_set_is_initial (GdmDisplay *self,
gboolean initial)
{
g_debug ("GdmDisplay: initial: %s", initial? "yes" : "no");
self->priv->is_initial = initial;
}
static void
_gdm_display_set_allow_timed_login (GdmDisplay *self,
gboolean allow_timed_login)
{
g_debug ("GdmDisplay: allow timed login: %s", allow_timed_login? "yes" : "no");
self->priv->allow_timed_login = allow_timed_login;
}
static void
gdm_display_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
@@ -811,60 +821,63 @@ gdm_display_set_property (GObject *object,
case PROP_SESSION_CLASS:
_gdm_display_set_session_class (self, g_value_get_string (value));
break;
case PROP_SESSION_TYPE:
_gdm_display_set_session_type (self, g_value_get_string (value));
break;
case PROP_REMOTE_HOSTNAME:
_gdm_display_set_remote_hostname (self, g_value_get_string (value));
break;
case PROP_X11_DISPLAY_NUMBER:
_gdm_display_set_x11_display_number (self, g_value_get_int (value));
break;
case PROP_X11_DISPLAY_NAME:
_gdm_display_set_x11_display_name (self, g_value_get_string (value));
break;
case PROP_X11_COOKIE:
_gdm_display_set_x11_cookie (self, g_value_get_string (value));
break;
case PROP_IS_LOCAL:
_gdm_display_set_is_local (self, g_value_get_boolean (value));
break;
case PROP_ALLOW_TIMED_LOGIN:
_gdm_display_set_allow_timed_login (self, g_value_get_boolean (value));
break;
case PROP_LAUNCH_ENVIRONMENT:
_gdm_display_set_launch_environment (self, g_value_get_object (value));
break;
case PROP_IS_INITIAL:
_gdm_display_set_is_initial (self, g_value_get_boolean (value));
break;
+ case PROP_SESSION_REGISTERED:
+ _gdm_display_set_session_registered (self, g_value_get_boolean (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gdm_display_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GdmDisplay *self;
self = GDM_DISPLAY (object);
switch (prop_id) {
case PROP_ID:
g_value_set_string (value, self->priv->id);
break;
case PROP_STATUS:
g_value_set_int (value, self->priv->status);
break;
case PROP_SEAT_ID:
g_value_set_string (value, self->priv->seat_id);
break;
case PROP_SESSION_ID:
g_value_set_string (value, self->priv->session_id);
break;
case PROP_SESSION_CLASS:
@@ -881,60 +894,63 @@ gdm_display_get_property (GObject *object,
break;
case PROP_X11_DISPLAY_NAME:
g_value_set_string (value, self->priv->x11_display_name);
break;
case PROP_X11_COOKIE:
g_value_set_string (value, self->priv->x11_cookie);
break;
case PROP_X11_AUTHORITY_FILE:
g_value_take_string (value,
self->priv->access_file?
gdm_display_access_file_get_path (self->priv->access_file) : NULL);
break;
case PROP_IS_LOCAL:
g_value_set_boolean (value, self->priv->is_local);
break;
case PROP_IS_CONNECTED:
g_value_set_boolean (value, self->priv->xcb_connection != NULL);
break;
case PROP_LAUNCH_ENVIRONMENT:
g_value_set_object (value, self->priv->launch_environment);
break;
case PROP_IS_INITIAL:
g_value_set_boolean (value, self->priv->is_initial);
break;
case PROP_HAVE_EXISTING_USER_ACCOUNTS:
g_value_set_boolean (value, self->priv->have_existing_user_accounts);
break;
case PROP_DOING_INITIAL_SETUP:
g_value_set_boolean (value, self->priv->doing_initial_setup);
break;
+ case PROP_SESSION_REGISTERED:
+ g_value_set_boolean (value, priv->session_registered);
+ break;
case PROP_ALLOW_TIMED_LOGIN:
g_value_set_boolean (value, self->priv->allow_timed_login);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static gboolean
handle_get_id (GdmDBusDisplay *skeleton,
GDBusMethodInvocation *invocation,
GdmDisplay *self)
{
char *id;
gdm_display_get_id (self, &id, NULL);
gdm_dbus_display_complete_get_id (skeleton, invocation, id);
g_free (id);
return TRUE;
}
static gboolean
handle_get_remote_hostname (GdmDBusDisplay *skeleton,
GDBusMethodInvocation *invocation,
GdmDisplay *self)
{
char *hostname;
@@ -1197,60 +1213,68 @@ gdm_display_class_init (GdmDisplayClass *klass)
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_IS_LOCAL,
g_param_spec_boolean ("is-local",
NULL,
NULL,
TRUE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
PROP_IS_CONNECTED,
g_param_spec_boolean ("is-connected",
NULL,
NULL,
TRUE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_HAVE_EXISTING_USER_ACCOUNTS,
g_param_spec_boolean ("have-existing-user-accounts",
NULL,
NULL,
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_DOING_INITIAL_SETUP,
g_param_spec_boolean ("doing-initial-setup",
NULL,
NULL,
FALSE,
G_PARAM_READABLE));
+ g_object_class_install_property (object_class,
+ PROP_SESSION_REGISTERED,
+ g_param_spec_boolean ("session-registered",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
g_object_class_install_property (object_class,
PROP_LAUNCH_ENVIRONMENT,
g_param_spec_object ("launch-environment",
NULL,
NULL,
GDM_TYPE_LAUNCH_ENVIRONMENT,
G_PARAM_READWRITE));
g_object_class_install_property (object_class,
PROP_STATUS,
g_param_spec_int ("status",
"status",
"status",
-1,
G_MAXINT,
GDM_DISPLAY_UNMANAGED,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_type_class_add_private (klass, sizeof (GdmDisplayPrivate));
}
static void
gdm_display_init (GdmDisplay *self)
{
self->priv = GDM_DISPLAY_GET_PRIVATE (self);
self->priv->creation_time = time (NULL);
self->priv->server_timer = g_timer_new ();
}
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index b147d73db..bff602a07 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -789,60 +789,89 @@ gdm_manager_handle_register_display (GdmDBusManager *manager,
if (session != NULL) {
GPid pid;
if (x11_display_name != NULL) {
g_object_set (G_OBJECT (session), "display-name", x11_display_name, NULL);
g_object_set (G_OBJECT (display), "x11-display-name", x11_display_name, NULL);
}
/* FIXME: this should happen in gdm-session.c when the session is opened
*/
if (tty != NULL)
g_object_set (G_OBJECT (session), "display-device", tty, NULL);
pid = gdm_session_get_pid (session);
if (pid > 0) {
add_session_record (self, session, pid, SESSION_RECORD_LOGIN);
}
}
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_MANAGED, NULL);
gdm_dbus_manager_complete_register_display (GDM_DBUS_MANAGER (manager),
invocation);
g_clear_pointer (&x11_display_name, g_free);
g_clear_pointer (&tty, g_free);
return TRUE;
}
+static gboolean
+gdm_manager_handle_register_session (GdmDBusManager *manager,
+ GDBusMethodInvocation *invocation,
+ GVariant *details)
+{
+ GdmManager *self = GDM_MANAGER (manager);
+ GdmDisplay *display;
+ const char *sender;
+ GDBusConnection *connection;
+
+ sender = g_dbus_method_invocation_get_sender (invocation);
+ connection = g_dbus_method_invocation_get_connection (invocation);
+
+ get_display_and_details_for_bus_sender (self, connection, sender, &display,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL);
+
+ g_debug ("GdmManager: trying to register new session on display %p", display);
+
+ if (display != NULL)
+ g_object_set (G_OBJECT (display), "session-registered", TRUE, NULL);
+ else
+ g_debug ("GdmManager: No display, not registering");
+
+ gdm_dbus_manager_complete_register_session (GDM_DBUS_MANAGER (manager),
+ invocation);
+
+ return TRUE;
+}
+
static gboolean
gdm_manager_handle_open_session (GdmDBusManager *manager,
GDBusMethodInvocation *invocation)
{
GdmManager *self = GDM_MANAGER (manager);
const char *sender;
GDBusConnection *connection;
GdmDisplay *display = NULL;
GdmSession *session = NULL;
const char *address;
GPid pid = 0;
uid_t uid = (uid_t) -1;
uid_t allowed_user;
g_debug ("GdmManager: trying to open new session");
sender = g_dbus_method_invocation_get_sender (invocation);
connection = g_dbus_method_invocation_get_connection (invocation);
get_display_and_details_for_bus_sender (self, connection, sender, &display, NULL, NULL, NULL, &pid, &uid, NULL, NULL);
if (display == NULL) {
g_dbus_method_invocation_return_error_literal (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
_("No session available"));
return TRUE;
}
#ifdef HAVE_LIBXDMCP
@@ -1167,60 +1196,61 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager
g_hash_table_insert (self->priv->open_reauthentication_requests,
GINT_TO_POINTER (pid),
invocation);
} else if (is_login_screen) {
g_dbus_method_invocation_return_error_literal (invocation,
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Login screen only allowed to open reauthentication channels for running sessions");
return TRUE;
} else {
char *address;
address = open_temporary_reauthentication_channel (self,
seat_id,
session_id,
pid,
uid,
is_remote);
gdm_dbus_manager_complete_open_reauthentication_channel (GDM_DBUS_MANAGER (manager),
invocation,
address);
g_free (address);
}
return TRUE;
}
static void
manager_interface_init (GdmDBusManagerIface *interface)
{
interface->handle_register_display = gdm_manager_handle_register_display;
+ interface->handle_register_session = gdm_manager_handle_register_session;
interface->handle_open_session = gdm_manager_handle_open_session;
interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel;
}
static gboolean
display_is_on_seat0 (GdmDisplay *display)
{
gboolean is_on_seat0 = TRUE;
char *seat_id = NULL;
g_object_get (G_OBJECT (display), "seat-id", &seat_id, NULL);
if (g_strcmp0 (seat_id, "seat0") != 0) {
is_on_seat0 = FALSE;
}
g_free (seat_id);
return is_on_seat0;
}
static gboolean
get_timed_login_details (GdmManager *manager,
char **usernamep,
int *delayp)
{
gboolean res;
gboolean enabled;
int delay;
diff --git a/daemon/gdm-manager.xml b/daemon/gdm-manager.xml
index f11f3fb73..92ef1d02d 100644
--- a/daemon/gdm-manager.xml
+++ b/daemon/gdm-manager.xml
@@ -1,16 +1,19 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node name="/org/gnome/DisplayManager/Manager">
<interface name="org.gnome.DisplayManager.Manager">
<method name="RegisterDisplay">
<arg name="details" direction="in" type="a{ss}"/>
</method>
+ <method name="RegisterSession">
+ <arg name="details" direction="in" type="a{sv}"/>
+ </method>
<method name="OpenSession">
<arg name="address" direction="out" type="s"/>
</method>
<method name="OpenReauthenticationChannel">
<arg name="username" direction="in" type="s"/>
<arg name="address" direction="out" type="s"/>
</method>
<property name="Version" type="s" access="read"/>
</interface>
</node>
--
2.28.0

File diff suppressed because it is too large Load Diff

View File

@ -7,135 +7,73 @@
%define desktop_file_utils_version 0.2.90
%define nss_version 3.11.1
%global tarball_version %%(echo %{version} | tr '~' '.')
Name: gdm
Epoch: 1
Version: 3.28.3
Release: 39%{?dist}
Version: 40.0
Release: 15%{?dist}
Summary: The GNOME Display Manager
License: GPLv2+
URL: https://wiki.gnome.org/Projects/GDM
Source0: http://download.gnome.org/sources/gdm/3.28/gdm-%{version}.tar.xz
Source0: http://download.gnome.org/sources/gdm/40/gdm-%{version}.tar.xz
Source1: org.gnome.login-screen.gschema.override
Patch00001: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch
Patch10001: 0001-utils-add-new-gdm-disable-wayland-binary.patch
# Lets customers using vendor nvidia driver pick wayland sessions from the login screen
Patch10001: 0001-local-display-factory-Provide-more-flexibility-for-c.patch
Patch10002: 0002-libgdm-Sort-session-list.patch
Patch10003: 0003-xdmcp-display-factory-Set-supported-session-types-fo.patch
Patch20001: 0001-display-access-file-drop-unused-function.patch
# Race fix
Patch40001: 0001-display-Handle-failure-before-display-registration.patch
Patch30001: 0001-data-disable-wayland-for-proprietary-nvidia-machines.patch
Patch30002: 0001-data-disable-wayland-on-server-chips-and-dual-gpu-se.patch
Patch30003: 0001-data-enable-wayland-on-cirrus.patch
Patch30004: 0001-data-only-disable-wayland-on-passthrough-virt-setups.patch
# Don't bother building gdm-screenshot, nothing uses it
Patch50001: 0001-utils-Drop-gdm-screenshot.patch
Patch40001: 0001-local-display-factory-pause-for-a-few-seconds-before.patch
# Questionable feature to support logging in over multiple XDMCP consoles at the same time
Patch60001: 0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch
Patch60002: 0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch
Patch60003: 0003-session-ensure-login-screen-over-XDMCP-connects-to-i.patch
Patch60001: 0001-session-ensure-login-screen-over-XDMCP-connects-to-i.patch
# Upstream change that's moderately risky so revert it
Patch70001: 0001-Revert-gdm-wayland-x-session-don-t-overwrite-user-en.patch
Patch70001: 0001-worker-don-t-load-user-settings-for-program-sessions.patch
Patch70002: 0002-session-support-new-accountsservice-Session-and-Sess.patch
Patch70003: 0003-daemon-save-os-release-in-accountsservice.patch
Patch70004: 0004-daemon-handle-upgrades-from-RHEL-7.patch
# Crash fix
Patch80001: 0001-local-display-factory-Don-t-try-to-respawn-displays-.patch
Patch80001: 0001-session-worker-expose-worker-state-enum-to-type-syst.patch
Patch80002: 0002-session-worker-kill-user-sessions-when-stop-gdm-serv.patch
Patch80003: 0003-session-worker-uninitialize-pam-if-worker-is-killed.patch
Patch80004: 0004-data-reap-gdm-sessions-on-shutdown.patch
# Non-upstreamable workarounds
Patch66610001: 0001-local-display-factory-pause-for-a-few-seconds-before.patch
Patch66620001: 0001-data-reap-gdm-sessions-on-shutdown.patch
# CVE-2019-3825
Patch90001: 0001-manager-don-t-kill-timed-login-session-immediately-a.patch
Patch90002: 0002-manager-session-Add-some-debugging-around-starting-r.patch
Patch90003: 0003-session-Don-t-allow-greeter-operations-on-an-running.patch
Patch90004: 0004-GdmManager-Don-t-perform-timed-login-if-session-gets.patch
# Non-upstreamable integration patches
Patch99910001: 0001-Honor-initial-setup-being-disabled-by-distro-install.patch
Patch100001: 0001-manager-allow-multiple-xdmcp-logins-for-the-same-use.patch
Patch100002: 0002-gdm-x-session-run-session-bus-on-non-seat0-seats.patch
Patch99920001: 0001-worker-don-t-load-user-settings-for-program-sessions.patch
Patch99920002: 0002-session-support-new-accountsservice-Session-and-Sess.patch
Patch99920003: 0003-daemon-save-os-release-in-accountsservice.patch
Patch99920004: 0004-daemon-handle-upgrades-from-RHEL-7.patch
Patch110001: 0001-display-ask-accountservice-if-there-are-users-rather.patch
Patch99920006: 0001-data-Disable-network-configuration-on-login-screen.patch
Patch120001: 0001-daemon-fix-wayland-detection-when-deciding-to-bypass.patch
Patch99930001: 0001-data-add-system-dconf-databases-to-gdm-profile.patch
# This truckload of patches reworks how VT allocation is done, and makes sure
# the login screen is killed after login
# https://bugzilla.redhat.com/show_bug.cgi?id=1618481
Patch200001: 0001-display-factory-avoid-removing-a-display-from-store-.patch
Patch200002: 0002-local-display-factory-Add-gdm_local_display_factory_.patch
Patch200003: 0003-local-display-factory-Use-correct-session-type-for-n.patch
Patch200004: 0004-manager-make-get_login_window_session_id-fail-if-no-.patch
Patch200005: 0005-manager-avoid-leaking-session_id.patch
Patch200006: 0006-manager-gracefully-handle-the-case-of-no-session-for.patch
Patch200007: 0007-common-dedupe-gdm_get_login_window_session_id.patch
Patch200008: 0008-common-dedupe-activate_session_id.patch
Patch200009: 0009-manager-plug-leak-in-maybe_activate_other_session.patch
Patch200010: 0010-manager-start-login-screen-if-old-one-is-finished.patch
Patch200011: 0011-manager-don-t-bail-if-session-disappears-out-from-un.patch
Patch200012: 0012-daemon-try-harder-to-get-to-a-login-screen-at-logout.patch
Patch200013: 0013-local-display-factory-ensure-non-seat0-codepath-does.patch
Patch200014: 0014-daemon-kill-and-restart-greeter-on-demand-under-wayl.patch
Patch200015: 0015-local-display-factory-add-more-debug-messages-to-new.patch
Patch200016: 0016-local-display-factory-don-t-start-two-greeters-at-st.patch
Patch200017: 0017-session-worker-don-t-switch-VTs-if-we-re-already-on-.patch
Patch200018: 0018-session-worker-fix-current-vt-detection-short-circui.patch
Patch200019: 0019-local-display-factory-don-t-jump-to-failed-display.patch
Patch200020: 0020-local-display-factory-add-some-more-debug-statements.patch
Patch200021: 0021-local-display-factory-ignore-spurios-SeatNew-signal-.patch
Patch200022: 0022-common-remove-unnecessary-free.patch
Patch200023: 0023-common-don-t-bail-if-session-disappears-out-from-und.patch
Patch200024: 0024-manager-better-logind-handling.patch
Patch200025: 0025-session-worker-clear-VT-before-jumping-to-it.patch
Patch200026: 0026-manager-don-t-set-ran_once-after-running-initial-set.patch
Patch200027: 0027-manager-start-initial-setup-right-away.patch
Patch200028: 0028-gdm-wayland-session-gdm-x-session-register-after-del.patch
Patch200029: 0029-local-display-factory-defer-killing-greeter-until-ne.patch
Patch200030: 0030-daemon-Move-the-waiting-the-session-to-have-taken-ov.patch
Patch200031: 0031-local-display-factory-don-t-autoreap-initial-setup.patch
Patch200032: 0032-manager-rework-how-autologin-is-figured-out.patch
Patch200033: 0033-manager-correct-display-confusion.patch
Patch200034: 0034-manager-don-t-run-autologin-display-on-tty1.patch
Patch200035: 0035-local-display-factory-Remove-initial-VT-is-in-use-ch.patch
Patch200036: 0036-local-display-factory-Remove-same-VT-so-don-t-switch.patch
Patch200037: 0037-local-display-factory-handle-reviving-displays-that-.patch
Patch200038: 0038-manager-don-t-kill-initial-setup-before-starting-use.patch
Patch200039: 0039-manager-do-initial-setup-post-work-in-manager-code.patch
Patch200040: 0040-display-store-make-foreach-ignore-callback-return-va.patch
Patch200041: 0041-xdmcp-display-factory-don-t-return-value-from-foreac.patch
Patch200042: 0042-GdmLocalDisplayFactory-Store-VT-number-not-tty-ident.patch
Patch200043: 0043-gdm-session-worker-Drop-login_vt-assuming-it-is-GDM_.patch
Patch200044: 0044-session-worker-ensure-initial-vt-is-never-picked-for.patch
Patch200045: 0045-local-display-factory-Always-force-login-screen-to-V.patch
Patch200046: 0046-gdm-x-session-tell-x-server-to-not-vt-switch.patch
Patch200047: 0047-local-display-factory-kill-X-on-login-just-like-wayl.patch
Patch200048: 0048-manager-don-t-kill-initial-setup-right-away-with-Xor.patch
Patch200049: 0049-GdmManager-GdmDisplay-Add-RegisterSession-method.patch
Patch200050: 0050-Allow-sessions-to-register-with-GDM.patch
Patch200051: 0051-display-Handle-failure-before-display-registration.patch
Patch99940001: 0001-data-disable-wayland-on-certain-hardware.patch
# CVE-2020-16125
Patch210001: 0001-display-Exit-with-failure-if-loading-existing-users-.patch
# CVE-2020-27837
Patch220001: 0001-session-worker-Don-t-switch-back-VTs-until-session-i.patch
Patch300001: 0001-manager-Don-t-leak-session-objects.patch
Patch300002: 0002-session-Don-t-leak-remote-greeter-interface.patch
Patch300003: 0003-xdmcp-display-factory-Clear-launch-environment-when-.patch
Patch900001: 0001-data-add-system-dconf-databases-to-gdm-profile.patch
BuildRequires: pam-devel >= 0:%{pam_version}
BuildRequires: accountsservice-devel
BuildRequires: audit-libs-devel >= %{libauditver}
BuildRequires: dconf
BuildRequires: desktop-file-utils >= %{desktop_file_utils_version}
BuildRequires: libtool automake autoconf
BuildRequires: libattr-devel
BuildRequires: gettext
BuildRequires: gettext-devel
BuildRequires: git
BuildRequires: keyutils-libs-devel
BuildRequires: libXdmcp-devel
BuildRequires: libattr-devel
BuildRequires: libdmx-devel
BuildRequires: audit-libs-devel >= %{libauditver}
BuildRequires: autoconf automake libtool
BuildRequires: intltool
%ifnarch s390 s390x ppc ppc64
BuildRequires: xorg-x11-server-Xorg
%endif
BuildRequires: meson
BuildRequires: nss-devel >= %{nss_version}
BuildRequires: pam-devel >= 0:%{pam_version}
BuildRequires: pkgconfig(accountsservice) >= 0.6.3
BuildRequires: pkgconfig(check)
BuildRequires: pkgconfig(gobject-introspection-1.0)
@ -149,10 +87,15 @@ BuildRequires: pkgconfig(systemd)
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(xau)
BuildRequires: pkgconfig(xorg-server)
BuildRequires: libXdmcp-devel
BuildRequires: plymouth-devel
BuildRequires: systemd
BuildRequires: keyutils-libs-devel
BuildRequires: dconf
BuildRequires: systemd-devel
BuildRequires: which
%ifnarch s390 s390x ppc ppc64
BuildRequires: xorg-x11-server-Xorg
%endif
BuildRequires: xorg-x11-server-devel
BuildRequires: yelp-tools
Requires(pre): /usr/sbin/useradd
%{?systemd_requires}
@ -181,6 +124,10 @@ Requires: xorg-x11-xinit
Recommends: xorg-x11-server-Xorg
Conflicts: xorg-x11-server-Xorg < 1.20.8-4
# Until the greeter gets dynamic user support, it can't
# use a user bus
Requires: /usr/bin/dbus-run-session
Obsoletes: gdm-libs < 1:3.12.0-3
Provides: gdm-libs%{?_isa} = %{epoch}:%{version}-%{release}
@ -228,33 +175,22 @@ GDM specific authentication features.
%prep
%autosetup -S git
autoreconf -i -f
intltoolize -f
%build
%configure --with-pam-prefix=%{_sysconfdir} \
--with-run-dir=/run/gdm \
--with-default-path=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin \
--enable-split-authentication \
--enable-profiling \
--enable-console-helper \
--with-plymouth \
--with-selinux
# drop unneeded direct library deps with --as-needed
# libtool doesn't make this easy, so we do it the hard way
sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0 /g' -e 's/ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then/ func_append compile_command " -Wl,-O1,--as-needed"\n func_append finalize_command " -Wl,-O1,--as-needed"\n\0/' libtool
%make_build
%meson -Dpam-prefix=%{_sysconfdir} \
-Drun-dir=/run/gdm \
-Dudev-dir=%{_udevrulesdir} \
-Ddefault-path=/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin \
-Dprofiling=true \
-Dplymouth=enabled \
-Dselinux=enabled
%meson_build
%install
mkdir -p %{buildroot}%{_sysconfdir}/gdm/Init
mkdir -p %{buildroot}%{_sysconfdir}/gdm/PreSession
mkdir -p %{buildroot}%{_sysconfdir}/gdm/PostSession
%make_install
%meson_install
install -p -m644 -D %{SOURCE5} %{buildroot}%{_localstatedir}/lib/gdm/.config/pulse/default.pa
@ -266,6 +202,9 @@ cp -a %{SOURCE1} %{buildroot}%{_datadir}/glib-2.0/schemas
# docs go elsewhere
rm -rf %{buildroot}/%{_prefix}/doc
# we're not doing user sessions in rhel 8
rm -rf %{buildroot}%{_prefix}/lib/systemd/user
# create log dir
mkdir -p %{buildroot}/var/log/gdm
@ -277,10 +216,11 @@ mkdir -p %{buildroot}/run/gdm
mkdir -p %{buildroot}%{_sysconfdir}/dconf/db/gdm.d/locks
rm -f %{buildroot}%{_bindir}/gdm-screenshot
find %{buildroot} -name '*.a' -delete
find %{buildroot} -name '*.la' -delete
cat << EOF > %{buildroot}%{_libexecdir}/gdm-disable-wayland
#!/bin/sh
%{_libexecdir}/gdm-runtime-config set daemon WaylandEnable false
EOF
chmod a+x %{buildroot}%{_libexecdir}/gdm-disable-wayland
%find_lang gdm --with-gnome
@ -351,7 +291,7 @@ fi
%systemd_postun gdm.service
%files -f gdm.lang
%doc AUTHORS NEWS README
%doc AUTHORS NEWS README.md
%license COPYING
%dir %{_sysconfdir}/gdm
%config(noreplace) %{_sysconfdir}/gdm/custom.conf
@ -371,10 +311,10 @@ fi
%dir %{_sysconfdir}/gdm/PostLogin
%dir %{_sysconfdir}/dconf/db/gdm.d
%dir %{_sysconfdir}/dconf/db/gdm.d/locks
%{_datadir}/pixmaps/*.png
%{_datadir}/glib-2.0/schemas/org.gnome.login-screen.gschema.xml
%{_datadir}/glib-2.0/schemas/org.gnome.login-screen.gschema.override
%{_libexecdir}/gdm-disable-wayland
%{_libexecdir}/gdm-runtime-config
%{_libexecdir}/gdm-host-chooser
%{_libexecdir}/gdm-session-worker
%{_libexecdir}/gdm-simple-chooser
@ -394,6 +334,7 @@ fi
%{_datadir}/gdm/locale.alias
%{_datadir}/gdm/gdb-cmd
%{_datadir}/gnome-session/sessions/gnome-login.session
%{_datadir}/polkit-1/rules.d/org.gnome.gdm.rules
%{_libdir}/girepository-1.0/Gdm-1.0.typelib
%{_libdir}/security/pam_gdm.so
%{_libdir}/libgdm*.so*
@ -403,8 +344,6 @@ fi
%attr(0700, gdm, gdm) %dir %{_localstatedir}/lib/gdm/.config/pulse
%attr(0600, gdm, gdm) %{_localstatedir}/lib/gdm/.config/pulse/default.pa
%attr(0711, root, gdm) %dir /run/gdm
%attr(1755, root, gdm) %dir %{_localstatedir}/cache/gdm
%{_datadir}/icons/hicolor/*/*/*.png
%config %{_sysconfdir}/pam.d/gdm-pin
%config %{_sysconfdir}/pam.d/gdm-smartcard
%config %{_sysconfdir}/pam.d/gdm-fingerprint
@ -425,6 +364,44 @@ fi
%{_libdir}/pkgconfig/gdm-pam-extensions.pc
%changelog
* Wed Sep 15 2021 Ray Strode <rstrode@redhat.com> - 40.0-14
- Fix XDMCP
Resolves: #2004170
- Fix crash at shutdown
Related: #2004170
* Wed Sep 01 2021 Ray Strode <rstrode@redhat.com> - 40.0-13
- Disable Wayland on HyperV
- Fix Xorg fallback
Related: #1998989
* Thu Aug 19 2021 Ray Strode <rstrode@redhat.com> - 40.0-12
- Redisable on server chips since rebase
Related: #1909300
* Wed Aug 04 2021 Ray Strode <rstrode@redhat.com> - 40.0-11
- Read session settings from users even if they've never saved
before. Needed to support accountsservice templated user
defaults.
Related: #1812788
* Tue Jul 27 2021 Ray Strode <rstrode@redhat.com> - 40.0-10
- Let customers using vendor nvidia driver choose wayland sessions
Resolves: #1962211
- Drop unused patches
* Tue Jun 08 2021 Florian Müllner <fmuellner@redhat.com> - 40.0-3
- Disable network items on login screen
Resolves: #1935261
* Wed May 19 2021 Ray Strode <rstrode@redhat.com> - 40.0-2
- Fix workaround for systemd bug that's breaking X11 fallback
Resolves: #1962049
* Wed May 05 2021 Ray Strode <rstrode@redhat.com> - 40.0-1
- Rebase to 40.0
Resolves: #1909300
* Wed Jan 27 2021 Ray Strode <rstrode@redhat.com> - 3.28.3-39
- Ensure login screen display server is is killed at log in
- Pull in fixes for two security issues