fix CVE-2019-3825

This commit is contained in:
wangxiao65 2021-02-05 16:03:46 +08:00
parent 2c5b9c4b24
commit c4e04311b0
5 changed files with 447 additions and 1 deletions

33
CVE-2019-3825-1.patch Normal file
View File

@ -0,0 +1,33 @@
From 7726c81db92d2339fc468ed41c967f5412db66ed Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
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

226
CVE-2019-3825-2.patch Normal file
View File

@ -0,0 +1,226 @@
From d9d22a1c48a528873e3cc84a73fc868507b8dd4d Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
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

130
CVE-2019-3825-3.patch Normal file
View File

@ -0,0 +1,130 @@
From 94d9fec87960e3ff5f7b75dadcde2807db148fbd Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
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

50
CVE-2019-3825-4.patch Normal file
View File

@ -0,0 +1,50 @@
From dd45295425c5a843c30aa8797b02d59ff488acb8 Mon Sep 17 00:00:00 2001
From: Iain Lane <iainl@gnome.org>
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

View File

@ -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 <wangxiao65@huawei.com> - 1:3.30.1-10
- fix CVE-2019-3825
* Fri Dec 18 2020 Guoshuai Sun <sunguoshuai@huawei.com> - 1:3.30.1-9
- Gdm should recover automatically when killed