Blob Blame History Raw
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