diff --git a/SOURCES/dont-require-working-rdns.patch b/SOURCES/dont-require-working-rdns.patch new file mode 100644 index 0000000..231effb --- /dev/null +++ b/SOURCES/dont-require-working-rdns.patch @@ -0,0 +1,290 @@ +From 8ab57ebcf775bf97fc99c0315a4b7b29435c34c2 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 20 Apr 2016 17:07:53 -0400 +Subject: [PATCH] common: limit potentially expensive name lookups + +Right now we're doing name look ups when we don't have to. These +name look ups can cause lengthy timeouts in misconfigured environments. + +This commit reduces the name looks used by GDM to make it more resiliant +to failure. + +Ported from RHEL 6 to RHEL 7 by Ashish Shah +--- + common/gdm-address.c | 24 ++++++++++++------------ + 1 file changed, 12 insertions(+), 12 deletions(-) + +diff --git a/common/gdm-address.c b/common/gdm-address.c +index 3448038..a8b73e2 100644 +--- a/common/gdm-address.c ++++ b/common/gdm-address.c +@@ -193,159 +193,160 @@ gdm_address_equal (GdmAddress *a, + return FALSE; + } + + /* for debugging */ + static const char * + address_family_str (GdmAddress *address) + { + const char *str; + switch (address->ss->ss_family) { + case AF_INET: + str = "inet"; + break; + case AF_INET6: + str = "inet6"; + break; + case AF_UNIX: + str = "unix"; + break; + case AF_UNSPEC: + str = "unspecified"; + break; + default: + str = "unknown"; + break; + } + return str; + } + + static void + _gdm_address_debug (GdmAddress *address, +- const char *hostname, + const char *host, + const char *port) + { +- g_debug ("Address family:%d (%s) hostname:%s host:%s port:%s local:%d loopback:%d", ++ g_debug ("Address family:%d (%s) host:%s port:%s local:%d loopback:%d", ++ + address->ss->ss_family, + address_family_str (address) ? address_family_str (address) : "(null)", +- hostname ? hostname : "(null)", + host ? host : "(null)", + port ? port : "(null)", + gdm_address_is_local (address), + gdm_address_is_loopback (address)); + } + + void + gdm_address_debug (GdmAddress *address) + { +- char *hostname; +- char *host; +- char *port; ++ char *hostname = NULL; ++ char *host = NULL; ++ char *port = NULL; + +- gdm_address_get_hostname (address, &hostname); + gdm_address_get_numeric_info (address, &host, &port); + ++ _gdm_address_debug (address, host, port); ++ + g_free (hostname); + g_free (host); + g_free (port); + } + + gboolean + gdm_address_get_hostname (GdmAddress *address, + char **hostnamep) + { + char host [NI_MAXHOST]; + int res; + gboolean ret; + + g_return_val_if_fail (address != NULL, FALSE); + g_return_val_if_fail (address->ss != NULL, FALSE); + + ret = FALSE; + + host [0] = '\0'; + res = getnameinfo ((const struct sockaddr *)address->ss, + (int) gdm_sockaddr_len (address->ss), + host, sizeof (host), + NULL, 0, + 0); + if (res == 0) { + ret = TRUE; + goto done; + } else { + const char *err_msg; + + err_msg = gai_strerror (res); + g_warning ("Unable to lookup hostname: %s", + err_msg ? err_msg : "(null)"); +- _gdm_address_debug (address, NULL, NULL, NULL); ++ _gdm_address_debug (address, NULL, NULL); ++ + } + + /* try numeric? */ + + done: + if (hostnamep != NULL) { + *hostnamep = g_strdup (host); + } + + return ret; + } + + gboolean + gdm_address_get_numeric_info (GdmAddress *address, + char **hostp, + char **servp) + { + char host [NI_MAXHOST]; + char serv [NI_MAXSERV]; + int res; + gboolean ret; + + g_return_val_if_fail (address != NULL, FALSE); + g_return_val_if_fail (address->ss != NULL, FALSE); + + ret = FALSE; + + host [0] = '\0'; + serv [0] = '\0'; + res = getnameinfo ((const struct sockaddr *)address->ss, + (int) gdm_sockaddr_len (address->ss), + host, sizeof (host), + serv, sizeof (serv), + NI_NUMERICHOST | NI_NUMERICSERV); + if (res != 0) { + const char *err_msg; + + err_msg = gai_strerror (res); + g_warning ("Unable to lookup numeric info: %s", + err_msg ? err_msg : "(null)"); +- _gdm_address_debug (address, NULL, NULL, NULL); ++ _gdm_address_debug (address, NULL, NULL); + } else { + ret = TRUE; + } + + if (servp != NULL) { + if (g_str_has_prefix (serv, "::ffff:")) { + *servp = g_strdup (serv + 7); + } else { + *servp = g_strdup (serv); + } + } + if (hostp != NULL) { + if (g_str_has_prefix (host, "::ffff:")) { + *hostp = g_strdup (host + 7); + } else { + *hostp = g_strdup (host); + } + } + + return ret; + } + + gboolean + gdm_address_is_loopback (GdmAddress *address) + { + g_return_val_if_fail (address != NULL, FALSE); + g_return_val_if_fail (address->ss != NULL, FALSE); + + switch (address->ss->ss_family){ + #ifdef AF_INET6 +@@ -377,94 +378,93 @@ add_local_siocgifconf (GList **list) + perror ("socket"); + return; + } + + ifc.ifc_len = sizeof (buf); + ifc.ifc_buf = buf; + if (ioctl (sock, SIOCGIFCONF, (char *) &ifc) < 0) { + perror ("SIOCGIFCONF"); + close (sock); + return; + } + + /* Get IP address of each active IP network interface. */ + the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + + for (ifr = ifc.ifc_req; ifr < the_end; ifr++) { + if (ifr->ifr_addr.sa_family == AF_INET) { + /* IP net interface */ + ifreq = *ifr; + + if (ioctl (sock, SIOCGIFFLAGS, (char *) &ifreq) < 0) { + perror("SIOCGIFFLAGS"); + } else if (ifreq.ifr_flags & IFF_UP) { /* active interface */ + if (ioctl (sock, SIOCGIFADDR, (char *) &ifreq) < 0) { + perror("SIOCGIFADDR"); + } else { + GdmAddress *address; + address = gdm_address_new_from_sockaddr ((struct sockaddr *)&ifreq.ifr_addr, + sizeof (struct sockaddr)); + +- gdm_address_debug (address); +- + *list = g_list_append (*list, address); + } + } + } + + /* Support for variable-length addresses. */ + #ifdef HAS_SA_LEN + ifr = (struct ifreq *) ((caddr_t) ifr + + ifr->ifr_addr.sa_len - sizeof(struct sockaddr)); + #endif + } + + close (sock); + } + + static void + add_local_addrinfo (GList **list) + { + char hostbuf[BUFSIZ]; + struct addrinfo *result; + struct addrinfo *res; + struct addrinfo hints; + + hostbuf[BUFSIZ-1] = '\0'; + if (gethostname (hostbuf, BUFSIZ-1) != 0) { + g_debug ("%s: Could not get server hostname, using localhost", "gdm_peek_local_address_list"); + snprintf (hostbuf, BUFSIZ-1, "localhost"); + } + + memset (&hints, 0, sizeof (hints)); + hints.ai_family = AF_UNSPEC; +- hints.ai_flags = AI_CANONNAME; ++ hints.ai_flags = AI_CANONNAME | AI_NUMERICHOST; ++ + + g_debug ("GdmAddress: looking up hostname: %s", hostbuf); + result = NULL; + if (getaddrinfo (hostbuf, NULL, &hints, &result) != 0) { + g_debug ("%s: Could not get address from hostname!", "gdm_peek_local_address_list"); + + return; + } + + for (res = result; res != NULL; res = res->ai_next) { + GdmAddress *address; + + g_debug ("family=%d sock_type=%d protocol=%d flags=0x%x canonname=%s\n", + res->ai_family, + res->ai_socktype, + res->ai_protocol, + res->ai_flags, + res->ai_canonname ? res->ai_canonname : "(null)"); + address = gdm_address_new_from_sockaddr (res->ai_addr, res->ai_addrlen); + *list = g_list_append (*list, address); + } + + if (result != NULL) { + freeaddrinfo (result); + result = NULL; + } + } + + const GList * + gdm_address_peek_local_list (void) +-- +2.8.1 + diff --git a/SOURCES/fix-language-chooser.patch b/SOURCES/fix-language-chooser.patch new file mode 100644 index 0000000..072c778 --- /dev/null +++ b/SOURCES/fix-language-chooser.patch @@ -0,0 +1,175 @@ +From 2d6d95e4e90fae014fc5615ab39fe64ba49d9a29 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 21 Jan 2016 10:27:58 -0500 +Subject: [PATCH] session: make sure greeter is GNOME session even if gnome + isn't installed + +We figure out the XDG_CURRENT_DESKTOP by looking at the session that's +use for login. For the greeter, we don't use a session, at all, but +instead a directly specified program. Still, we're determining the +XDG_CURRENT_DESKTOP for the greeter based on what default session +gets picked. On KDE only setups, the greeter will get marked as +a KDE session which will prevent gnome-settings-daemon from starting +properly. + +This commit changes the code so that greeter sessions, don't rely +on the default session desktop file. + +https://bugzilla.gnome.org/show_bug.cgi?id=760943 +--- + daemon/gdm-session.c | 24 +++++++++++++++--------- + 1 file changed, 15 insertions(+), 9 deletions(-) + +diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c +index 647db86..ae94999 100644 +--- a/daemon/gdm-session.c ++++ b/daemon/gdm-session.c +@@ -2502,60 +2502,64 @@ get_session_name (GdmSession *self) + + return get_default_session_name (self); + } + + static char * + get_session_command (GdmSession *self) + { + gboolean res; + char *command; + const char *session_name; + + session_name = get_session_name (self); + + command = NULL; + res = get_session_command_for_name (session_name, &command); + if (! res) { + g_critical ("Cannot find a command for specified session: %s", session_name); + exit (1); + } + + return command; + } + + static gchar * + get_session_desktop_names (GdmSession *self) + { + gchar *filename; + GKeyFile *keyfile; + gchar *desktop_names = NULL; + ++ if (self->priv->selected_program != NULL) { ++ return g_strdup ("GNOME-Greeter:GNOME"); ++ } ++ + filename = g_strdup_printf ("%s.desktop", get_session_name (self)); + keyfile = load_key_file_for_file (filename, NULL); + if (keyfile != NULL) { + gchar **names; + + names = g_key_file_get_string_list (keyfile, G_KEY_FILE_DESKTOP_GROUP, + "DesktopNames", NULL, NULL); + if (names != NULL) { + desktop_names = g_strjoinv (":", names); + + g_strfreev (names); + } + } + + g_key_file_free (keyfile); + g_free (filename); + return desktop_names; + } + + void + gdm_session_set_environment_variable (GdmSession *self, + const char *key, + const char *value) + { + g_return_if_fail (key != NULL); + g_return_if_fail (value != NULL); + + g_hash_table_replace (self->priv->environment, + g_strdup (key), + g_strdup (value)); +@@ -2565,69 +2569,71 @@ static void + set_up_session_language (GdmSession *self) + { + char **environment; + int i; + const char *value; + + environment = g_listenv (); + for (i = 0; environment[i] != NULL; i++) { + if (strcmp (environment[i], "LANG") != 0 && + strcmp (environment[i], "LANGUAGE") != 0 && + !g_str_has_prefix (environment[i], "LC_")) { + continue; + } + + value = g_getenv (environment[i]); + + gdm_session_set_environment_variable (self, + environment[i], + value); + } + g_strfreev (environment); + } + + static void + set_up_session_environment (GdmSession *self) + { + GdmSessionDisplayMode display_mode; + gchar *desktop_names; + char *locale; + +- gdm_session_set_environment_variable (self, +- "GDMSESSION", +- get_session_name (self)); +- gdm_session_set_environment_variable (self, +- "DESKTOP_SESSION", +- get_session_name (self)); +- gdm_session_set_environment_variable (self, +- "XDG_SESSION_DESKTOP", +- get_session_name (self)); ++ if (self->priv->selected_program == NULL) { ++ gdm_session_set_environment_variable (self, ++ "GDMSESSION", ++ get_session_name (self)); ++ gdm_session_set_environment_variable (self, ++ "DESKTOP_SESSION", ++ get_session_name (self)); ++ gdm_session_set_environment_variable (self, ++ "XDG_SESSION_DESKTOP", ++ get_session_name (self)); ++ } + + desktop_names = get_session_desktop_names (self); + if (desktop_names != NULL) { + gdm_session_set_environment_variable (self, "XDG_CURRENT_DESKTOP", desktop_names); + } + + set_up_session_language (self); + + locale = g_strdup (get_default_language_name (self)); + + if (locale != NULL && locale[0] != '\0') { + gdm_session_set_environment_variable (self, + "LANG", + locale); + gdm_session_set_environment_variable (self, + "GDM_LANG", + locale); + } + + g_free (locale); + + display_mode = gdm_session_get_display_mode (self); + if (display_mode == GDM_SESSION_DISPLAY_MODE_REUSE_VT) { + gdm_session_set_environment_variable (self, + "DISPLAY", + self->priv->display_name); + + if (self->priv->user_x11_authority_file != NULL) { + gdm_session_set_environment_variable (self, + "XAUTHORITY", +-- +2.8.1 + diff --git a/SOURCES/fix-post-login.patch b/SOURCES/fix-post-login.patch new file mode 100644 index 0000000..27356e9 --- /dev/null +++ b/SOURCES/fix-post-login.patch @@ -0,0 +1,350 @@ +From c3f39b437f6ef32174f322bd107071cdf1379d12 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 18 Apr 2016 16:09:08 -0400 +Subject: [PATCH 1/2] worker: run PostLogin/PreSession scripts later + +Right now we run them while the login screen is still up, so +they have no way of showing UI to the user. + +This commit moves them until after the login screen is torn +down. +--- + daemon/gdm-session-worker.c | 34 ++++++++++++++++++---------------- + 1 file changed, 18 insertions(+), 16 deletions(-) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index acc826b..e07d32e 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -1793,60 +1793,78 @@ out: + } + + static gboolean + gdm_session_worker_start_session (GdmSessionWorker *worker, + GError **error) + { + struct passwd *passwd_entry; + pid_t session_pid; + int error_code; + + gdm_get_pwent_for_name (worker->priv->username, &passwd_entry); + if (worker->priv->is_program_session) { + g_debug ("GdmSessionWorker: opening session for program '%s'", + worker->priv->arguments[0]); + } else { + g_debug ("GdmSessionWorker: opening user session with program '%s'", + worker->priv->arguments[0]); + } + + error_code = PAM_SUCCESS; + + #ifdef ENABLE_WAYLAND_SUPPORT + /* If we're in new vt mode, jump to the new vt now. There's no need to jump for + * the other two modes: in the logind case, the session will activate itself when + * ready, and in the reuse server case, we're already on the correct VT. */ + if (worker->priv->display_mode == GDM_SESSION_DISPLAY_MODE_NEW_VT) { + jump_to_vt (worker, worker->priv->session_vt); + } + #endif + ++ if (!worker->priv->is_program_session && !run_script (worker, GDMCONFDIR "/PostLogin")) { ++ g_set_error (error, ++ GDM_SESSION_WORKER_ERROR, ++ GDM_SESSION_WORKER_ERROR_OPENING_SESSION, ++ "Failed to execute PostLogin script"); ++ error_code = PAM_ABORT; ++ goto out; ++ } ++ ++ if (!worker->priv->is_program_session && !run_script (worker, GDMCONFDIR "/PreSession")) { ++ g_set_error (error, ++ GDM_SESSION_WORKER_ERROR, ++ GDM_SESSION_WORKER_ERROR_OPENING_SESSION, ++ "Failed to execute PreSession script"); ++ error_code = PAM_ABORT; ++ goto out; ++ } ++ + session_pid = fork (); + + if (session_pid < 0) { + g_set_error (error, + GDM_SESSION_WORKER_ERROR, + GDM_SESSION_WORKER_ERROR_OPENING_SESSION, + "%s", g_strerror (errno)); + error_code = PAM_ABORT; + goto out; + } + + if (session_pid == 0) { + const char * const * environment; + char *home_dir; + int stdin_fd = -1, stdout_fd = -1, stderr_fd = -1; + gboolean has_journald = FALSE; + sigset_t mask; + + /* Leak the TTY into the session as stdin so that it stays open + * without any races. */ + if (worker->priv->session_tty_fd > 0) { + dup2 (worker->priv->session_tty_fd, STDIN_FILENO); + close (worker->priv->session_tty_fd); + worker->priv->session_tty_fd = -1; + } else { + stdin_fd = open ("/dev/null", O_RDWR); + dup2 (stdin_fd, STDIN_FILENO); + close (stdin_fd); + } + +@@ -2186,93 +2204,77 @@ gdm_session_worker_open_session (GdmSessionWorker *worker, + + g_assert (worker->priv->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED); + g_assert (geteuid () == 0); + + switch (worker->priv->display_mode) { + case GDM_SESSION_DISPLAY_MODE_REUSE_VT: + if (!set_up_for_current_vt (worker, error)) { + return FALSE; + } + break; + #ifdef ENABLE_WAYLAND_SUPPORT + 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; + #endif + } + + flags = 0; + + if (worker->priv->is_program_session) { + flags |= PAM_SILENT; + } + +- if (!run_script (worker, GDMCONFDIR "/PostLogin")) { +- g_set_error (error, +- GDM_SESSION_WORKER_ERROR, +- GDM_SESSION_WORKER_ERROR_OPENING_SESSION, +- "Failed to execute PostLogin script"); +- return FALSE; +- } +- + 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; + + #ifdef WITH_SYSTEMD + session_id = gdm_session_worker_get_environment_variable (worker, "XDG_SESSION_ID"); + #endif + +- /* FIXME: should we do something here? +- * Note that error return status from PreSession script should +- * be ignored in the case of a X-GDM-BypassXsession session, which can +- * be checked by calling: +- * gdm_session_bypasses_xsession (session) +- */ +- run_script (worker, GDMCONFDIR "/PreSession"); +- + #ifdef WITH_CONSOLE_KIT + register_ck_session (worker); + + if (session_id == NULL) { + session_id = get_ck_session_id (worker); + } + #endif + + 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); +-- +2.8.1 + + +From ebc5a37f8f4a287df4255cbcdf5d51f7a8fe9b44 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 19 Apr 2016 11:02:08 -0400 +Subject: [PATCH 2/2] manager: handle session failing to start + +Right now if a session fails really early in the start up +process, we fail to handle it. + +This commit fixes that. +--- + daemon/gdm-manager.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 33064ea..72ea968 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -1475,60 +1475,69 @@ on_session_started (GdmSession *session, + + session_id = gdm_session_get_session_id (session); + g_object_set (GDM_SLAVE (slave), "session-id", session_id, NULL); + } + } + + static void + remove_user_session (GdmManager *manager, + GdmSession *session) + { + GList *node; + GdmDisplay *display; + + display = get_display_for_user_session (session); + + if (display != NULL) { + gdm_display_unmanage (display); + gdm_display_finish (display); + } + + node = g_list_find (manager->priv->user_sessions, session); + + if (node != NULL) { + manager->priv->user_sessions = g_list_delete_link (manager->priv->user_sessions, node); + gdm_session_close (session); + g_object_unref (session); + } + } + + static void ++on_session_start_failed (GdmSession *session, ++ const char *service_name, ++ GdmManager *manager) ++{ ++ g_debug ("GdmManager: session failed to start"); ++ remove_user_session (manager, session); ++} ++ ++static void + on_user_session_exited (GdmSession *session, + int code, + GdmManager *manager) + { + g_debug ("GdmManager: session exited with status %d", code); + remove_user_session (manager, 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 * + query_ck_for_display_device (GdmManager *manager, + GdmDisplay *display) + { + char *out; + char *command; + char *display_name = NULL; + int status; + gboolean res; + GError *error; + + g_object_get (G_OBJECT (display), + "x11-display-name", &display_name, +@@ -1894,60 +1903,64 @@ create_seed_session_for_display (GdmManager *manager, + manager); + g_signal_connect (session, + "client-connected", + G_CALLBACK (on_session_client_connected), + manager); + g_signal_connect (session, + "client-disconnected", + G_CALLBACK (on_session_client_disconnected), + manager); + g_signal_connect (session, + "cancelled", + G_CALLBACK (on_session_cancelled), + manager); + g_signal_connect (session, + "conversation-started", + G_CALLBACK (on_session_conversation_started), + manager); + g_signal_connect (session, + "conversation-stopped", + G_CALLBACK (on_session_conversation_stopped), + manager); + g_signal_connect (session, + "session-opened", + G_CALLBACK (on_session_opened), + manager); + g_signal_connect (session, + "session-started", + G_CALLBACK (on_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-seed-session", g_object_ref (session), (GDestroyNotify) g_object_unref); + + start_autologin_conversation_if_necessary (manager, display, 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); +-- +2.8.1 + diff --git a/SOURCES/fix-xdmcp-unlock.patch b/SOURCES/fix-xdmcp-unlock.patch new file mode 100644 index 0000000..f3f6c6f --- /dev/null +++ b/SOURCES/fix-xdmcp-unlock.patch @@ -0,0 +1,93 @@ +From 0b10f4d8e8ef2e6db519a1e5f8884e71c08403d9 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 1 Aug 2016 11:25:47 -0400 +Subject: [PATCH] manager: don't try to activate session if session not on seat + +If a session is not associated with a seat (because it's remote), +then we shouldn't try to activate the session. Activating sessions, +really only means anything on seat0 (where it means to change +the active VT). + +This prevents premature failure before unlock on XDMCP. +--- + daemon/gdm-manager.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c +index 72ea968..ed9a437 100644 +--- a/daemon/gdm-manager.c ++++ b/daemon/gdm-manager.c +@@ -851,64 +851,66 @@ get_display_and_details_for_bus_sender (GdmManager *self, + } + out: + g_free (session_id); + } + + static gboolean + switch_to_compatible_user_session (GdmManager *manager, + GdmSession *session, + gboolean fail_if_already_switched) + { + gboolean res; + gboolean ret; + const char *username; + const char *seat_id; + const char *ssid_to_activate; + GdmSession *existing_session; + + ret = FALSE; + + username = gdm_session_get_username (session); + seat_id = gdm_session_get_display_seat_id (session); + + if (!fail_if_already_switched) { + session = NULL; + } + + 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); +- res = activate_session_id (manager, seat_id, ssid_to_activate); +- if (! res) { +- g_debug ("GdmManager: unable to activate session: %s", ssid_to_activate); +- goto out; ++ if (seat_id != NULL) { ++ res = activate_session_id (manager, 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); + } + } else { + goto out; + } + + 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_seed_session_for_display (GdmDisplay *display) + { + if (display == NULL) { + return NULL; + } + +-- +2.7.4 + diff --git a/SOURCES/notify-xdmcp-about-session-end.patch b/SOURCES/notify-xdmcp-about-session-end.patch new file mode 100644 index 0000000..a5ddc1f --- /dev/null +++ b/SOURCES/notify-xdmcp-about-session-end.patch @@ -0,0 +1,503 @@ +From cb356d992cec51cb87e2243edadec6a3d3348bd7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 19 Jul 2016 16:54:43 -0400 +Subject: [PATCH 1/3] xdmcp-display-factory: notify remote display when session + ended + +gnome-shell and the session dbus daemon don't automatically exit +when gnome-session does. They, instead, wait for the display to +exit or regenerate. If the display is remote, that won't happen +until the keep alive timeout. + +This commit changes GDM to explicitly notify the remote display +when the session is over, so that it can regenerate immediately. +--- + daemon/gdm-xdmcp-display-factory.c | 15 ++++++++++++++- + 1 file changed, 14 insertions(+), 1 deletion(-) + +diff --git a/daemon/gdm-xdmcp-display-factory.c b/daemon/gdm-xdmcp-display-factory.c +index d01f7ff..4132dd1 100644 +--- a/daemon/gdm-xdmcp-display-factory.c ++++ b/daemon/gdm-xdmcp-display-factory.c +@@ -183,61 +183,64 @@ struct GdmXdmcpDisplayFactoryPrivate + /* configuration */ + guint port; + gboolean use_multicast; + char *multicast_address; + gboolean honor_indirect; + char *willing_script; + guint max_displays_per_host; + guint max_displays; + guint max_pending_displays; + guint max_wait; + guint max_wait_indirect; + }; + + enum { + PROP_0, + PROP_PORT, + PROP_USE_MULTICAST, + PROP_MULTICAST_ADDRESS, + PROP_HONOR_INDIRECT, + PROP_WILLING_SCRIPT, + PROP_MAX_DISPLAYS_PER_HOST, + PROP_MAX_DISPLAYS, + PROP_MAX_PENDING_DISPLAYS, + PROP_MAX_WAIT, + PROP_MAX_WAIT_INDIRECT, + }; + + static void gdm_xdmcp_display_factory_class_init (GdmXdmcpDisplayFactoryClass *klass); + static void gdm_xdmcp_display_factory_init (GdmXdmcpDisplayFactory *manager); + static void gdm_xdmcp_display_factory_finalize (GObject *object); +- ++static void gdm_xdmcp_send_alive (GdmXdmcpDisplayFactory *factory, ++ GdmAddress *address, ++ CARD16 dspnum, ++ CARD32 sessid); + static gpointer xdmcp_display_factory_object = NULL; + + G_DEFINE_TYPE (GdmXdmcpDisplayFactory, gdm_xdmcp_display_factory, GDM_TYPE_DISPLAY_FACTORY) + + /* Theory of operation: + * + * Process idles waiting for UDP packets on port 177. + * Incoming packets are decoded and checked against tcp_wrapper. + * + * A typical session looks like this: + * + * Display sends Query/BroadcastQuery to Manager. + * + * Manager selects an appropriate authentication scheme from the + * display's list of supported ones and sends Willing/Unwilling. + * + * Assuming the display accepts the auth. scheme it sends back a + * Request. + * + * If the manager accepts to service the display (i.e. loadavg is low) + * it sends back an Accept containing a unique SessionID. The + * SessionID is stored in an accept queue by the Manager. Should the + * manager refuse to start a session a Decline is sent to the display. + * + * The display returns a Manage request containing the supplied + * SessionID. The manager will then start a session on the display. In + * case the SessionID is not on the accept queue the manager returns + * Refuse. If the manager fails to open the display for connections + * Failed is returned. + * +@@ -2026,68 +2029,78 @@ on_hostname_selected (GdmXdmcpChooserDisplay *display, + g_warning ("Unable to get address: %s", gai_strerror (gaierr)); + g_free (xdmcp_port); + return; + } + g_free (xdmcp_port); + + /* just take the first one */ + ai = ai_list; + + if (ai != NULL) { + 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_display_status_changed (GdmDisplay *display, + GParamSpec *arg1, + GdmXdmcpDisplayFactory *factory) + { + int status; + GdmDisplayStore *store; ++ GdmAddress *address; ++ gint32 session_number; ++ int display_number; + + store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory)); + + 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); + break; + case GDM_DISPLAY_FAILED: + gdm_display_store_remove (store, display); + break; + case GDM_DISPLAY_UNMANAGED: + break; + case GDM_DISPLAY_PREPARED: + break; + case GDM_DISPLAY_MANAGED: + break; + default: + g_assert_not_reached (); + break; + } + } + + 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); + +-- +2.7.4 + + +From e35b483f4c32d4095ea0d67991fff1e2b8339f2c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 20 Jul 2016 11:43:45 -0400 +Subject: [PATCH 2/3] worker: kill process group when session exits + +Send a hangup signal to the session pg when it exits, so things +have a chance to get cleaned up. +--- + daemon/gdm-session-worker.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c +index e07d32e..bc4a7ea 100644 +--- a/daemon/gdm-session-worker.c ++++ b/daemon/gdm-session-worker.c +@@ -1603,60 +1603,62 @@ run_script (GdmSessionWorker *worker, + worker->priv->username, + worker->priv->x11_display_name, + worker->priv->display_is_local? NULL : worker->priv->hostname, + worker->priv->x11_authority_file); + } + + 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); + + #ifdef WITH_CONSOLE_KIT + close_ck_session (worker); + #endif + + gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS); + + gdm_dbus_worker_emit_session_exited (GDM_DBUS_WORKER (worker), + worker->priv->service, + status); + ++ killpg (pid, SIGHUP); ++ + worker->priv->child_pid = -1; + + run_script (worker, GDMCONFDIR "/PostSession"); + } + + 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) +-- +2.7.4 + + +From fa6bc4c99f49a9c6ccd5cf1728eabf71685c34d0 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 20 Jul 2016 17:23:05 -0400 +Subject: [PATCH 3/3] slave: close display when we're done with it. + +When we're done with the display we need to kill off any clients +that are lingering and close our own connection to the display. +--- + configure.ac | 2 +- + daemon/gdm-slave.c | 38 ++++++++++++++++++++++++++++++++++++++ + 2 files changed, 39 insertions(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index a131535..1ac2801 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -63,61 +63,61 @@ dnl --------------------------------------------------------------------------- + GLIB_REQUIRED_VERSION=2.36.0 + GTK_REQUIRED_VERSION=2.91.1 + LIBCANBERRA_GTK_REQUIRED_VERSION=0.4 + ACCOUNTS_SERVICE_REQUIRED_VERSION=0.6.12 + + EXTRA_COMPILE_WARNINGS(yes) + + PKG_CHECK_MODULES(GTHREAD, gthread-2.0) + AC_SUBST(GTHREAD_CFLAGS) + AC_SUBST(GTHREAD_LIBS) + + PKG_CHECK_MODULES(COMMON, + gobject-2.0 >= $GLIB_REQUIRED_VERSION + gio-2.0 >= $GLIB_REQUIRED_VERSION + gio-unix-2.0 >= $GLIB_REQUIRED_VERSION + ) + AC_SUBST(COMMON_CFLAGS) + AC_SUBST(COMMON_LIBS) + + PKG_CHECK_MODULES(DAEMON, + gobject-2.0 >= $GLIB_REQUIRED_VERSION + gio-2.0 >= $GLIB_REQUIRED_VERSION + gio-unix-2.0 >= $GLIB_REQUIRED_VERSION + accountsservice >= $ACCOUNTS_SERVICE_REQUIRED_VERSION + ) + AC_SUBST(DAEMON_CFLAGS) + AC_SUBST(DAEMON_LIBS) + + GLIB_GSETTINGS + +-PKG_CHECK_MODULES(XLIB, x11 xau xrandr, , ++PKG_CHECK_MODULES(XLIB, x11 xau xrandr x11-xcb, , + [AC_PATH_XTRA + if test "x$no_x" = xyes; then + AC_MSG_ERROR("no (requires X development libraries)") + else + XLIB_LIBS="$X_PRE_LIBS $X_LIBS -lXau -lX11 -lXext -lXrandr $X_EXTRA_LIBS" + XLIB_CFLAGS=$X_CFLAGS + fi]) + AC_SUBST(XLIB_CFLAGS) + AC_SUBST(XLIB_LIBS) + + PKG_CHECK_MODULES(GTK, + gtk+-3.0 >= $GTK_REQUIRED_VERSION + ) + AC_SUBST(GTK_CFLAGS) + AC_SUBST(GTK_LIBS) + + PKG_CHECK_MODULES(CANBERRA_GTK, + libcanberra-gtk3 >= $LIBCANBERRA_GTK_REQUIRED_VERSION + ) + AC_SUBST(CANBERRA_GTK_CFLAGS) + AC_SUBST(CANBERRA_GTK_LIBS) + + AC_ARG_WITH(selinux, + AS_HELP_STRING([--with-selinux], + [Add SELinux support]),, + with_selinux=auto) + + PKG_CHECK_MODULES(LIBSELINUX, libselinux, have_selinux=yes, have_selinux=no) + + use_selinux=no +diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c +index b4bbcfd..3a22cc6 100644 +--- a/daemon/gdm-slave.c ++++ b/daemon/gdm-slave.c +@@ -11,65 +11,68 @@ + * 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 + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + + #include + #include + #include + #include + + #include /* for Display */ ++#include + #include /* for XA_PIXMAP */ + #include /* for watch cursor */ + #include + #include + ++#include ++ + #ifdef WITH_SYSTEMD + #include + #endif + + #include "gdm-common.h" + #include "gdm-xerrors.h" + + #include "gdm-slave.h" + #include "gdm-display.h" + #include "gdm-display-glue.h" + + #include "gdm-server.h" + + #define GDM_SLAVE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SLAVE, GdmSlavePrivate)) + + struct GdmSlavePrivate + { + GPid pid; + guint output_watch_id; + guint error_watch_id; + + Display *server_display; + + char *session_id; + + GdmDisplay *display; + + /* cached display values */ + char *display_name; + int display_number; +@@ -453,60 +456,95 @@ gdm_slave_real_start (GdmSlave *slave) + g_error_free (error); + return FALSE; + } + + error = NULL; + res = gdm_display_get_seat_id (slave->priv->display, &slave->priv->display_seat_id, &error); + if (! res) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + return FALSE; + } + + error = NULL; + res = gdm_display_is_initial (slave->priv->display, &slave->priv->display_is_initial, &error); + if (! res) { + g_warning ("Failed to get value: %s", error->message); + g_error_free (error); + return FALSE; + } + + return TRUE; + } + + static gboolean + gdm_slave_real_stop (GdmSlave *slave) + { + g_debug ("GdmSlave: Stopping slave"); + + g_clear_object (&slave->priv->display); + ++ if (slave->priv->server_display) { ++ xcb_connection_t *connection; ++ const xcb_setup_t *setup; ++ ++ /* These 3 bits are reserved/unused by the X protocol */ ++ guint32 unused_bits = 0b11100000000000000000000000000000; ++ XID highest_client, client; ++ guint32 client_increment; ++ ++ connection = XGetXCBConnection (slave->priv->server_display); ++ setup = xcb_get_setup (connection); ++ ++ /* resource_id_mask is the bits given to each client for ++ * addressing resources */ ++ highest_client = (XID) ~unused_bits & ~setup->resource_id_mask; ++ client_increment = setup->resource_id_mask + 1; ++ ++ gdm_error_trap_push (); ++ ++ /* Kill every client but ourselves, then close our own connection ++ */ ++ for (client = 0; ++ client <= highest_client; ++ client += client_increment) { ++ ++ if (client != setup->resource_id_base) ++ XKillClient (slave->priv->server_display, client); ++ } ++ ++ XCloseDisplay (slave->priv->server_display); ++ gdm_error_trap_pop (); ++ ++ slave->priv->server_display = NULL; ++ } ++ + return TRUE; + } + + gboolean + gdm_slave_start (GdmSlave *slave) + { + gboolean ret; + + g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE); + + g_debug ("GdmSlave: starting slave"); + + g_object_ref (slave); + ret = GDM_SLAVE_GET_CLASS (slave)->start (slave); + g_object_unref (slave); + + return ret; + } + + gboolean + gdm_slave_stop (GdmSlave *slave) + { + gboolean ret; + + g_return_val_if_fail (GDM_IS_SLAVE (slave), FALSE); + + g_debug ("GdmSlave: stopping slave"); + + g_object_ref (slave); + +-- +2.7.4 + diff --git a/SPECS/gdm.spec b/SPECS/gdm.spec index f5c10ef..6377707 100644 --- a/SPECS/gdm.spec +++ b/SPECS/gdm.spec @@ -12,7 +12,7 @@ Summary: The GNOME Display Manager Name: gdm Version: 3.14.2 -Release: 12%{?dist} +Release: 19%{?dist} Epoch: 1 License: GPLv2+ Group: User Interface/X @@ -26,6 +26,11 @@ Patch2: fix-lang-changes.patch Patch3: audit-4.patch Patch4: fix-restarts.patch Patch10: clear-screen.patch +Patch11: fix-post-login.patch +Patch12: fix-language-chooser.patch +Patch13: dont-require-working-rdns.patch +Patch14: notify-xdmcp-about-session-end.patch +Patch15: fix-xdmcp-unlock.patch Patch98: system-dconf.patch Patch99: classic-session.patch @@ -76,7 +81,7 @@ Requires: dconf Requires: gnome-keyring-pam Requires: gnome-session Requires: gnome-settings-daemon >= 2.21.92 -Requires: gnome-shell +Requires: gnome-shell >= 3.14.2 Requires: iso-codes # We need 1.0.4-5 since it lets us use "localhost" in auth cookies Requires: libXau >= 1.0.4-4 @@ -120,6 +125,11 @@ files needed to build custom greeters. %patch3 -p1 -b .audit-4 %patch4 -p1 -b .fix-restarts %patch10 -p1 -b .clear-screen +%patch11 -p1 -b .fix-post-login +%patch12 -p1 -b .fix-language-chooser +%patch13 -p1 -b .dont-require-working-rdns +%patch14 -p1 -b .notify-xdmcp-about-session-end +%patch15 -p1 -b .fix-xdmcp-unlock %patch98 -p1 -b .system-dconf %patch99 -p1 -b .classic-session @@ -322,6 +332,38 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || : %{_libdir}/pkgconfig/gdm.pc %changelog +* Wed Sep 21 2016 Ray Strode - 3.14.2-19 +- Add error traps around XKillClient calls, fixes regression + on logout + Resolves: #1377987 + +* Tue Jul 19 2016 Ray Strode - 3.14.2-18 +- Fix unlock with XDMCP + Resolves: #1315342 +- Inform remote display about session exiting when using + XDMCP + Resolves: #1313059 + +* Tue Jul 12 2016 Ray Strode - 3.14.2-17 +- Add versioned requires with gnome-shell + Resolves: #1294546 + +* Wed Apr 20 2016 Ray Strode - 3.14.2-16 +- Be more resiliant against flakey DNS with XDMCP + Resolves: #1286631 + +* Wed Apr 20 2016 Ray Strode - 3.14.2-15 +- Fix language chooser on KDE only systems + Resolves: #1298753 + +* Tue Apr 19 2016 Ray Strode - 3.14.2-14 +- Fix ups to previous patch + Related: #1282577 + +* Mon Apr 18 2016 Ray Strode 3.14.2-13 +- Allow PostLogin script to show windows + Resolves: #1282577 + * Tue Aug 18 2015 Ray Strode 3.14.2-12 - don't log to systemd journal so logs end up in the same place they did in 7.1