From a8984a81c2e887623d69ec9989ae8a5025f7bd47 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 18 Jun 2019 16:12:46 +0200 Subject: [PATCH] xwayland: Generate a Xauth file and pass this to Xwayland when starting it Before this commit, sudo x11-app, e.g. sudo gvim /etc/some-file, fails when running a Wayland session. Where as doing this under a "GNOME on Xorg" session works fine. For a user switching from the Xorg session to the Wayland session, this is regression, which we want to avoid. This commit fixes this by creating and passing an xauth file to Xwayland when mutter starts it. Just like gdm or startx pass a xauth file to Xorg when they start Xorg. Fixes #643 https://gitlab.gnome.org/GNOME/mutter/issues/643 --- meson.build | 1 + src/meson.build | 1 + src/wayland/meta-wayland-private.h | 1 + src/wayland/meta-wayland.c | 11 +++- src/wayland/meta-xwayland.c | 81 ++++++++++++++++++++++++++++++ 5 files changed, 94 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index adc9faacc..d88a8653d 100644 --- a/meson.build +++ b/meson.build @@ -116,6 +116,7 @@ xrandr_dep = dependency('xrandr', version: xrandr_req) xcb_randr_dep = dependency('xcb-randr') xcb_res_dep = dependency('xcb-res') xinerama_dep = dependency('xinerama') +xau_dep = dependency('xau') ice_dep = dependency('ice') atk_dep = dependency('atk', version: atk_req) libcanberra_dep = dependency('libcanberra', version: libcanberra_req) diff --git a/src/meson.build b/src/meson.build index 53db81e85..805b9a20e 100644 --- a/src/meson.build +++ b/src/meson.build @@ -101,6 +101,7 @@ if have_x11 x11_xcb_dep, xcb_randr_dep, xcb_res_dep, + xau_dep, ] if have_sm diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h index f2410be4c..594088535 100644 --- a/src/wayland/meta-wayland-private.h +++ b/src/wayland/meta-wayland-private.h @@ -52,6 +52,7 @@ typedef struct struct wl_client *client; struct wl_resource *xserver_resource; char *display_name; + char *auth_file; GCancellable *xserver_died_cancellable; GSubprocess *proc; diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c index f6ce88ee6..dee5cdd59 100644 --- a/src/wayland/meta-wayland.c +++ b/src/wayland/meta-wayland.c @@ -361,6 +361,12 @@ meta_wayland_override_display_name (const char *display_name) _display_name_override = g_strdup (display_name); } +static const char * +meta_wayland_get_xwayland_auth_file (MetaWaylandCompositor *compositor) +{ + return compositor->xwayland_manager.auth_file; +} + void meta_wayland_init (void) { @@ -438,7 +444,10 @@ meta_wayland_init (void) } if (meta_should_autostart_x11_display ()) - set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor)); + { + set_gnome_env ("DISPLAY", meta_wayland_get_xwayland_display_name (compositor)); + set_gnome_env ("XAUTHORITY", meta_wayland_get_xwayland_auth_file (compositor)); + } set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor)); } diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index 43bf4c1e3..92a2224b2 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include "compositor/meta-surface-actor-wayland.h" #include "meta/main.h" @@ -438,6 +441,75 @@ choose_xdisplay (MetaXWaylandManager *manager) return TRUE; } +G_DEFINE_AUTOPTR_CLEANUP_FUNC (FILE, fclose) + +static gboolean +prepare_auth_file (MetaXWaylandManager *manager) +{ + Xauth auth_entry = { 0 }; + g_autoptr (FILE) fp = NULL; + char hostname[HOST_NAME_MAX + 1]; + char auth_data[16]; + int fd; + + manager->auth_file = g_build_filename (g_get_user_runtime_dir (), + ".mutter-Xwaylandauth.XXXXXX", + NULL); + + if (gethostname (hostname, HOST_NAME_MAX) < 0) + g_strlcpy (hostname, "localhost", HOST_NAME_MAX); + + if (getrandom (auth_data, sizeof (auth_data), 0) != sizeof (auth_data)) + { + g_warning ("Failed to get random data: %s", g_strerror (errno)); + return FALSE; + } + + auth_entry.family = FamilyLocal; + auth_entry.address = hostname; + auth_entry.address_length = strlen (auth_entry.address); + auth_entry.name = (char *) "MIT-MAGIC-COOKIE-1"; + auth_entry.name_length = strlen (auth_entry.name); + auth_entry.data = auth_data; + auth_entry.data_length = sizeof (auth_data); + + fd = g_mkstemp (manager->auth_file); + if (fd < 0) + { + g_warning ("Failed to open Xauthority file: %s", g_strerror (errno)); + return FALSE; + } + + fp = fdopen (fd, "w+"); + if (!fp) + { + g_warning ("Failed to open Xauthority stream: %s", g_strerror (errno)); + close (fd); + return FALSE; + } + + if (!XauWriteAuth (fp, &auth_entry)) + { + g_warning ("Error writing to Xauthority file: %s", g_strerror (errno)); + return FALSE; + } + + auth_entry.family = FamilyWild; + if (!XauWriteAuth (fp, &auth_entry)) + { + g_warning ("Error writing to Xauthority file: %s", g_strerror (errno)); + return FALSE; + } + + if (fflush (fp) == EOF) + { + g_warning ("Error writing to Xauthority file: %s", g_strerror (errno)); + return FALSE; + } + + return TRUE; +} + static void xserver_finished_init (MetaXWaylandManager *manager) { @@ -512,6 +584,7 @@ meta_xwayland_init_xserver (MetaXWaylandManager *manager) "-noreset", "-accessx", "-core", + "-auth", manager->auth_file, "-listen", "4", "-listen", "5", "-displayfd", "6", @@ -545,6 +618,9 @@ meta_xwayland_start (MetaXWaylandManager *manager, if (!choose_xdisplay (manager)) return FALSE; + if (!prepare_auth_file (manager)) + return FALSE; + manager->wayland_display = wl_display; return meta_xwayland_init_xserver (manager); } @@ -584,6 +660,11 @@ meta_xwayland_stop (MetaXWaylandManager *manager) unlink (path); g_clear_pointer (&manager->display_name, g_free); + if (manager->auth_file) + { + unlink (manager->auth_file); + g_clear_pointer (&manager->auth_file, g_free); + } if (manager->lock_file) { unlink (manager->lock_file);