From 5171e35a9706202ec17f0490762d12f2423c2724 Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Wed, 12 Aug 2020 19:30:04 +0200 Subject: [PATCH] xwayland: Add a setting to disable selected X extensions The X server, including Xwayland, can be compiled with different X11 extensions enabled at build time. When an X11 extension is built in the X server, it's usually also enabled at run time. Users can chose to disable those extensions at run time using the X server command line option "-extension". However, in the case of Xwayland, it is spawned automatically by the Wayland compositor, and the command line options are not configurable by users. Add a new setting to disable a selected set of X extension in Xwayland at startup, without needing to rebuild Xwayland. Of course, if Xwayland is not built with a given extension support in the first place (which is the default for the security extension for example), that option has no effect. https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1405 --- data/org.gnome.mutter.wayland.gschema.xml.in | 21 ++++++ src/backends/meta-settings-private.h | 8 +++ src/backends/meta-settings.c | 22 ++++++ src/wayland/meta-xwayland.c | 71 ++++++++++++++++---- 4 files changed, 108 insertions(+), 14 deletions(-) diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in index 23ce8386c..b8674b3ac 100644 --- a/data/org.gnome.mutter.wayland.gschema.xml.in +++ b/data/org.gnome.mutter.wayland.gschema.xml.in @@ -1,4 +1,10 @@ + + + + + + @@ -104,6 +110,21 @@ + + ["Security"] + Disable selected X extensions in Xwayland + + This option disables the selected X extensions in Xwayland if + Xwayland was built with support for those X extensions. + + This option has no effect if Xwayland was built without support + for the selected extensions. + + Xwayland needs to be restarted for this setting to take effect. + + + diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h index 5e5d8e8dd..91b3eb17a 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h @@ -37,6 +37,12 @@ typedef enum _MetaExperimentalFeature META_EXPERIMENTAL_FEATURE_AUTOSTART_XWAYLAND = (1 << 3), } MetaExperimentalFeature; +typedef enum _MetaXwaylandExtension +{ + META_XWAYLAND_EXTENSION_SECURITY = (1 << 0), + META_XWAYLAND_EXTENSION_XTEST = (1 << 1), +} MetaXwaylandExtension; + #define META_TYPE_SETTINGS (meta_settings_get_type ()) G_DECLARE_FINAL_TYPE (MetaSettings, meta_settings, META, SETTINGS, GObject) @@ -69,4 +75,6 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); +int meta_settings_get_xwayland_disable_extensions (MetaSettings *settings); + #endif /* META_SETTINGS_PRIVATE_H */ diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c index 14a9ead22..f14dbfae6 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c @@ -68,6 +68,9 @@ struct _MetaSettings gboolean xwayland_allow_grabs; GPtrArray *xwayland_grab_allow_list_patterns; GPtrArray *xwayland_grab_deny_list_patterns; + + /* A bitmask of MetaXwaylandExtension enum */ + int xwayland_disable_extensions; }; G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT) @@ -387,6 +390,14 @@ update_xwayland_allow_grabs (MetaSettings *settings) "xwayland-allow-grabs"); } +static void +update_xwayland_disable_extensions (MetaSettings *settings) +{ + settings->xwayland_disable_extensions = + g_settings_get_flags (settings->wayland_settings, + "xwayland-disable-extension"); +} + static void wayland_settings_changed (GSettings *wayland_settings, gchar *key, @@ -401,6 +412,10 @@ wayland_settings_changed (GSettings *wayland_settings, { update_xwayland_grab_access_rules (settings); } + else if (g_str_equal (key, "xwayland-disable-extension")) + { + update_xwayland_disable_extensions (settings); + } } void @@ -418,6 +433,12 @@ meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) return (settings->xwayland_allow_grabs); } +int +meta_settings_get_xwayland_disable_extensions (MetaSettings *settings) +{ + return (settings->xwayland_disable_extensions); +} + MetaSettings * meta_settings_new (MetaBackend *backend) { @@ -471,6 +492,7 @@ meta_settings_init (MetaSettings *settings) update_experimental_features (settings); update_xwayland_grab_access_rules (settings); update_xwayland_allow_grabs (settings); + update_xwayland_disable_extensions (settings); } static void diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index 1b67c0a92..4a9d07ea9 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -39,8 +39,10 @@ #include #include +#include "backends/meta-settings-private.h" #include "core/main-private.h" #include "meta/main.h" +#include "meta/meta-backend.h" #include "wayland/meta-xwayland-surface.h" #include "x11/meta-x11-display-private.h" @@ -574,12 +576,25 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager, GAsyncReadyCallback callback, gpointer user_data) { + struct { + const char *extension_name; + MetaXwaylandExtension disable_extension; + } x11_extension_names[] = { + { "SECURITY", META_XWAYLAND_EXTENSION_SECURITY }, + { "XTEST", META_XWAYLAND_EXTENSION_XTEST }, + }; + int xwayland_client_fd[2]; int displayfd[2]; g_autoptr(GSubprocessLauncher) launcher = NULL; GSubprocessFlags flags; GError *error = NULL; g_autoptr (GTask) task = NULL; + MetaBackend *backend; + MetaSettings *settings; + const char *args[32]; + int xwayland_disable_extensions; + int i, j; task = g_task_new (NULL, cancellable, callback, user_data); g_task_set_source_tag (task, meta_xwayland_start_xserver); @@ -614,6 +629,11 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager, flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE; } + backend = meta_get_backend (); + settings = meta_backend_get_settings (backend); + xwayland_disable_extensions = + meta_settings_get_xwayland_disable_extensions (settings); + launcher = g_subprocess_launcher_new (flags); g_subprocess_launcher_take_fd (launcher, xwayland_client_fd[1], 3); @@ -624,23 +644,46 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager, g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE); - manager->proc = g_subprocess_launcher_spawn (launcher, &error, - XWAYLAND_PATH, - manager->public_connection.name, - "-rootless", - "-noreset", - "-accessx", - "-core", - "-auth", manager->auth_file, - "-listen", "4", - "-listen", "5", - "-displayfd", "6", + i = 0; + args[i++] = XWAYLAND_PATH; + args[i++] = manager->public_connection.name; + args[i++] = "-rootless"; + args[i++] = "-noreset"; + args[i++] = "-accessx"; + args[i++] = "-core"; + args[i++] = "-auth"; + args[i++] = manager->auth_file; + args[i++] = "-listen"; + args[i++] = "4"; + args[i++] = "-listen"; + args[i++] = "5"; + args[i++] = "-displayfd"; + args[i++] = "6", #ifdef HAVE_XWAYLAND_INITFD - "-initfd", "7", + args[i++] = "-initfd"; + args[i++] = "7"; #else - "-listen", "7", + args[i++] = "-listen"; + args[i++] = "7"; #endif - NULL); + for (j = 0; j < G_N_ELEMENTS (x11_extension_names); j++) + { + /* Make sure we don't go past the array size - We need room for + * 2 arguments, plus the last NULL terminator. + */ + if (i + 3 > G_N_ELEMENTS (args)) + break; + + if (xwayland_disable_extensions & x11_extension_names[j].disable_extension) + { + args[i++] = "-extension"; + args[i++] = x11_extension_names[j].extension_name; + } + } + /* Terminator */ + args[i++] = NULL; + + manager->proc = g_subprocess_launcher_spawnv (launcher, args, &error); if (!manager->proc) {