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
This commit is contained in:
Hans de Goede 2019-06-18 16:12:46 +02:00
parent 769a02b630
commit a8984a81c2
5 changed files with 94 additions and 1 deletions

View File

@ -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)

View File

@ -101,6 +101,7 @@ if have_x11
x11_xcb_dep,
xcb_randr_dep,
xcb_res_dep,
xau_dep,
]
if have_sm

View File

@ -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;

View File

@ -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 ("XAUTHORITY", meta_wayland_get_xwayland_auth_file (compositor));
}
set_gnome_env ("WAYLAND_DISPLAY", meta_wayland_get_wayland_display_name (compositor));
}

View File

@ -31,6 +31,9 @@
#include <glib.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/random.h>
#include <unistd.h>
#include <X11/Xauth.h>
#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);