From 5542f30a0e3575507e76ff038e0772130b3436e9 Mon Sep 17 00:00:00 2001 From: wangxiao65 <287608437@qq.com> Date: Fri, 5 Feb 2021 16:03:46 +0800 Subject: [PATCH] fix CVE-2019-3825 (cherry picked from commit c4e04311b00a42fb54b2ad2735f1c10a51f90fca) --- CVE-2019-3825-1.patch | 33 ++++++ CVE-2019-3825-2.patch | 226 ++++++++++++++++++++++++++++++++++++++++++ CVE-2019-3825-3.patch | 130 ++++++++++++++++++++++++ CVE-2019-3825-4.patch | 50 ++++++++++ gdm.spec | 9 +- 5 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 CVE-2019-3825-1.patch create mode 100644 CVE-2019-3825-2.patch create mode 100644 CVE-2019-3825-3.patch create mode 100644 CVE-2019-3825-4.patch diff --git a/CVE-2019-3825-1.patch b/CVE-2019-3825-1.patch new file mode 100644 index 0000000..a345722 --- /dev/null +++ b/CVE-2019-3825-1.patch @@ -0,0 +1,33 @@ +From 7726c81db92d2339fc468ed41c967f5412db66ed Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 6 Feb 2019 16:14:52 -0500 +Subject: [PATCH] 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 4d2ad9dec..dbf64473a 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1683,7 +1683,8 @@ on_start_user_session (StartUserSessionOperation *operation) + session_id); + + +- 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); +-- +GitLab + diff --git a/CVE-2019-3825-2.patch b/CVE-2019-3825-2.patch new file mode 100644 index 0000000..eec0d2f --- /dev/null +++ b/CVE-2019-3825-2.patch @@ -0,0 +1,226 @@ +From d9d22a1c48a528873e3cc84a73fc868507b8dd4d Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Thu, 31 Jan 2019 10:52:35 +0000 +Subject: [PATCH] manager,session: Add some debugging around starting + reauthentication + +There's a bug right now dealing with timed login and reauthentication, +but it's not clear what's going on by looking at the logs. + +This commit sprinkles some more logging throughout the code, to make +the bug easier to track. +--- + daemon/gdm-manager.c | 46 ++++++++++++++++++++++++++++++++++++++------ + daemon/gdm-session.c | 25 ++++++++++++++++++++---- + 2 files changed, 61 insertions(+), 10 deletions(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index dbf64473a..1e5719558 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -335,23 +335,40 @@ find_session_for_user_on_seat (GdmManager *manager, + + for (node = manager->priv->user_sessions; node != NULL; node = node->next) { + GdmSession *candidate_session = node->data; +- const char *candidate_username, *candidate_seat_id; ++ const char *candidate_username, *candidate_seat_id, *candidate_session_id; + +- if (candidate_session == dont_count_session) ++ candidate_session_id = gdm_session_get_session_id (candidate_session); ++ ++ if (candidate_session == dont_count_session) { ++ g_debug ("GdmSession: Ignoring session %s as requested", ++ candidate_session_id); + continue; ++ } + +- if (!gdm_session_is_running (candidate_session)) ++ if (!gdm_session_is_running (candidate_session)) { ++ g_debug ("GdmSession: Ignoring session %s as it isn't running", ++ candidate_session_id); + continue; ++ } + + candidate_username = gdm_session_get_username (candidate_session); + candidate_seat_id = gdm_session_get_display_seat_id (candidate_session); + ++ g_debug ("GdmManager: Considering session %s on seat %s belonging to user %s", ++ candidate_session_id, ++ candidate_seat_id, ++ 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; + } + +@@ -835,8 +852,12 @@ gdm_manager_handle_open_session (GdmDBusManager *manager, + #endif + if (session == NULL) { + session = get_user_session_for_display (display); ++ g_debug ("GdmSession: Considering session %s for username %s", ++ gdm_session_get_session_id (session), ++ gdm_session_get_username (session)); + + if (gdm_session_is_running (session)) { ++ g_debug ("GdmSession: the session is running, and therefore can't be used"); + g_dbus_method_invocation_return_error_literal (invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_ACCESS_DENIED, +@@ -1012,6 +1033,10 @@ open_temporary_reauthentication_channel (GdmManager *self, + environment); + g_strfreev (environment); + ++ g_debug ("GdmSession: Created session for temporary reauthentication channel for user %d (seat %s)", ++ (int) uid, ++ seat_id); ++ + g_object_set_data_full (G_OBJECT (session), + "caller-session-id", + g_strdup (session_id), +@@ -1091,11 +1116,13 @@ gdm_manager_handle_open_reauthentication_channel (GdmDBusManager *manager + } + + if (is_login_screen) { ++ g_debug ("GdmManager: looking for login screen session for user %s on seat %s", username, seat_id); + session = find_session_for_user_on_seat (self, + username, + seat_id, + NULL); + } else { ++ g_debug ("GdmManager: looking for user session on display"); + session = get_user_session_for_display (display); + } + +@@ -1918,7 +1945,7 @@ on_session_client_connected (GdmSession *session, + gboolean enabled; + gboolean allow_timed_login = FALSE; + +- g_debug ("GdmManager: client connected"); ++ g_debug ("GdmManager: client with pid %d connected", (int) pid_of_client); + + display = get_display_for_user_session (session); + +@@ -1964,7 +1991,7 @@ on_session_client_disconnected (GdmSession *session, + GPid pid_of_client, + GdmManager *manager) + { +- g_debug ("GdmManager: client disconnected"); ++ g_debug ("GdmManager: client with pid %d disconnected", (int) pid_of_client); + } + + typedef struct +@@ -2031,9 +2058,10 @@ on_session_conversation_started (GdmSession *session, + gboolean enabled; + char *username; + +- g_debug ("GdmManager: session conversation started for service %s", service_name); ++ g_debug ("GdmManager: session conversation started for service %s on session", service_name); + + if (g_strcmp0 (service_name, "gdm-autologin") != 0) { ++ g_debug ("GdmManager: ignoring session conversation since its not automatic login conversation"); + return; + } + +@@ -2143,6 +2171,12 @@ create_user_session_for_display (GdmManager *manager, + display_auth_file, + display_is_local, + NULL); ++ ++ g_debug ("GdmSession: Created user session for user %d on display %s (seat %s)", ++ (int) allowed_user, ++ display_id, ++ display_seat_id); ++ + g_free (display_name); + g_free (remote_hostname); + g_free (display_auth_file); +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 04f879a7a..09f471086 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -654,7 +654,10 @@ gdm_session_select_user (GdmSession *self, + 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); +@@ -1429,6 +1432,7 @@ gdm_session_handle_client_select_user (GdmDBusGreeter *greeter_interface, + 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; + } +@@ -1485,7 +1489,10 @@ gdm_session_handle_client_begin_auto_login (GdmDBusGreeter *greeter_inter + invocation); + } + +- g_debug ("GdmSession: begin auto login for user '%s'", username); ++ 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); + +@@ -1788,7 +1795,9 @@ setup_outside_server (GdmSession *self) + GDBusServer *server; + GError *error = NULL; + +- g_debug ("GdmSession: Creating D-Bus server for greeters and such"); ++ g_debug ("GdmSession: Creating D-Bus server for greeters and such for session %s (%p)", ++ gdm_session_get_session_id (self), ++ self); + + observer = g_dbus_auth_observer_new (); + g_signal_connect_object (observer, +@@ -2172,7 +2181,7 @@ gdm_session_start_conversation (GdmSession *self, + conversation->job = NULL; + } + +- g_debug ("GdmSession: starting conversation %s", service_name); ++ g_debug ("GdmSession: starting conversation %s for session (%p)", service_name, self); + + conversation = start_conversation (self, service_name); + +@@ -2331,6 +2340,10 @@ gdm_session_setup_for_user (GdmSession *self, + + update_session_type (self); + ++ g_debug ("GdmSession: Set up service %s for username %s on session (%p)", ++ service_name, ++ username, ++ self); + gdm_session_select_user (self, username); + + self->priv->is_program_session = FALSE; +@@ -2961,6 +2974,10 @@ gdm_session_start_reauthentication (GdmSession *session, + + g_return_if_fail (conversation != NULL); + ++ g_debug ("GdmSession: starting reauthentication for session %s for client with pid %d", ++ conversation->session_id, ++ (int) uid_of_caller); ++ + conversation->reauth_pid_of_caller = pid_of_caller; + + gdm_dbus_worker_call_start_reauthentication (conversation->worker_proxy, +-- +GitLab + diff --git a/CVE-2019-3825-3.patch b/CVE-2019-3825-3.patch new file mode 100644 index 0000000..4068ba8 --- /dev/null +++ b/CVE-2019-3825-3.patch @@ -0,0 +1,130 @@ +From 94d9fec87960e3ff5f7b75dadcde2807db148fbd Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Thu, 31 Jan 2019 17:51:52 +0000 +Subject: [PATCH] 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 09f471086..ca06608c4 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -1414,6 +1414,21 @@ gdm_session_handle_client_select_session (GdmDBusGreeter *greeter_interf + 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); +@@ -1428,6 +1443,22 @@ gdm_session_handle_client_select_user (GdmDBusGreeter *greeter_interface, + 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); +@@ -1444,6 +1475,20 @@ gdm_session_handle_client_start_session_when_ready (GdmDBusGreeter *greet + 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, +@@ -1462,6 +1507,20 @@ gdm_session_handle_get_timed_login_details (GdmDBusGreeter *greeter_inter + 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, +@@ -1484,6 +1543,22 @@ gdm_session_handle_client_begin_auto_login (GdmDBusGreeter *greeter_inter + 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); +-- +GitLab + diff --git a/CVE-2019-3825-4.patch b/CVE-2019-3825-4.patch new file mode 100644 index 0000000..6b2ca91 --- /dev/null +++ b/CVE-2019-3825-4.patch @@ -0,0 +1,50 @@ +From dd45295425c5a843c30aa8797b02d59ff488acb8 Mon Sep 17 00:00:00 2001 +From: Iain Lane +Date: Mon, 4 Feb 2019 15:12:38 +0000 +Subject: [PATCH] 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 1e5719558..b8619fbba 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1947,6 +1947,14 @@ on_session_client_connected (GdmSession *session, + + 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) { +-- +GitLab + diff --git a/gdm.spec b/gdm.spec index 6504eff..ed1dc97 100644 --- a/gdm.spec +++ b/gdm.spec @@ -1,7 +1,7 @@ Name: gdm Epoch: 1 Version: 3.30.1 -Release: 9 +Release: 10 Summary: A graphical display manager License: GPLv2+ URL: https://wiki.gnome.org/Projects/GDM @@ -9,6 +9,10 @@ Source0: http://download.gnome.org/sources/gdm/3.30/gdm-%{version}.tar. Patch0: 9000-add-openeuler-pam-config.patch Patch1: display-Use-autoptr-to-handle-errors-in-look-for-exi.patch Patch2: gdm-should-recover-automatically.patch +Patch3: CVE-2019-3825-1.patch +Patch4: CVE-2019-3825-2.patch +Patch5: CVE-2019-3825-3.patch +Patch6: CVE-2019-3825-4.patch BuildRequires: pam-devel >= 0:0.99.8.1-11 desktop-file-utils >= 0.2.90 BuildRequires: libtool automake autoconf libattr-devel gettext-devel libdmx-devel @@ -163,6 +167,9 @@ fi %{_libdir}/pkgconfig/*.pc %changelog +* Fri Feb 5 2021 wangxiao - 1:3.30.1-10 +- fix CVE-2019-3825 + * Fri Dec 18 2020 Guoshuai Sun - 1:3.30.1-9 - Gdm should recover automatically when killed -- Gitee