diff --git a/config.h.meson b/config.h.meson index 60fd1169e..5a290b014 100644 --- a/config.h.meson +++ b/config.h.meson @@ -70,3 +70,6 @@ /* Whether Xwayland has -initfd option */ #mesondefine HAVE_XWAYLAND_INITFD + +/* Whether the Xwayland supports +/-byteswappedclients */ +#mesondefine HAVE_XWAYLAND_BYTE_SWAPPED_CLIENTS diff --git a/data/org.cinnamon.muffin.wayland.gschema.xml.in b/data/org.cinnamon.muffin.wayland.gschema.xml.in index 5c4802052..55a50e4bd 100644 --- a/data/org.cinnamon.muffin.wayland.gschema.xml.in +++ b/data/org.cinnamon.muffin.wayland.gschema.xml.in @@ -103,6 +103,30 @@ + + false + Allow X11 clients with a different endianess to connect to Xwayland + + Allow connections from clients with an endianess different to that + of Xwayland. + + The X server byte-swapping code is a huge attack surface, much of + that code in Xwayland is prone to security issues. + + The use-case of byte-swapped clients is very niche, and disabled by + default in Xwayland. + + Enable this option to instruct Xwayland to accept connections from + X11 clients with a different endianess. + + This option has no effect if Xwayland does not support the command + line option +byteswappedclients/-byteswappedclients to control that + setting. + + Xwayland needs to be restarted for this setting to take effect. + + + diff --git a/meson.build b/meson.build index 13e77d05e..2ce0a674d 100644 --- a/meson.build +++ b/meson.build @@ -376,6 +376,7 @@ if cc.has_header_symbol('sys/prctl.h', 'prctl') endif have_xwayland_initfd = false +have_xwayland_byte_swapped_clients = false if have_wayland xwayland_dep = dependency('xwayland', required: false) @@ -416,6 +417,16 @@ if have_wayland if (have_xwayland_initfd) cdata.set('HAVE_XWAYLAND_INITFD', 1) endif + + # For Xwayland +/-byteswappedclients usage + if xwayland_dep.found() + have_xwayland_byte_swapped_clients = xwayland_dep.get_variable('have_byteswappedclients', + default_value: 'false') == 'true' + endif + + if (have_xwayland_byte_swapped_clients) + cdata.set('HAVE_XWAYLAND_BYTE_SWAPPED_CLIENTS', 1) + endif endif #xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules') @@ -465,19 +476,20 @@ output = [ '', ' Options:', '', - ' Wayland.................. ' + have_wayland.to_string(), - ' Wayland EGLStream........ ' + have_wayland_eglstream.to_string(), - ' Native Backend........... ' + have_native_backend.to_string(), - ' EGL Device............... ' + have_egl_device.to_string(), - ' Default driver........... ' + default_driver, - ' Remote desktop........... ' + have_remote_desktop.to_string(), - ' gudev.................... ' + have_libgudev.to_string(), - ' Wacom.................... ' + have_libwacom.to_string(), - ' SM....................... ' + have_sm.to_string(), - ' Startup notification..... ' + have_startup_notification.to_string(), - ' Introspection............ ' + have_introspection.to_string(), - ' Profiler................. ' + have_profiler.to_string(), - ' Xwayland initfd.......... ' + have_xwayland_initfd.to_string(), + ' Wayland.......................... ' + have_wayland.to_string(), + ' Wayland EGLStream................ ' + have_wayland_eglstream.to_string(), + ' Native Backend................... ' + have_native_backend.to_string(), + ' EGL Device....................... ' + have_egl_device.to_string(), + ' Default driver................... ' + default_driver, + ' Remote desktop................... ' + have_remote_desktop.to_string(), + ' gudev............................ ' + have_libgudev.to_string(), + ' Wacom............................ ' + have_libwacom.to_string(), + ' SM............................... ' + have_sm.to_string(), + ' Startup notification............. ' + have_startup_notification.to_string(), + ' Introspection.................... ' + have_introspection.to_string(), + ' Profiler......................... ' + have_profiler.to_string(), + ' Xwayland initfd.................. ' + have_xwayland_initfd.to_string(), + ' Xwayland byte-swapped clients.... ' + have_xwayland_byte_swapped_clients.to_string(), '', ' Tests:', '', diff --git a/src/backends/meta-settings-private.h b/src/backends/meta-settings-private.h index 8965e1cd4..9ed6b74cd 100644 --- a/src/backends/meta-settings-private.h +++ b/src/backends/meta-settings-private.h @@ -79,6 +79,8 @@ void meta_settings_get_xwayland_grab_patterns (MetaSettings *settings, gboolean meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings); +gboolean meta_settings_are_xwayland_byte_swapped_clients_allowed (MetaSettings *settings); + MetaX11ScaleMode meta_settings_get_x11_scale_mode (MetaSettings *settings); void meta_settings_enable_x11_fractional_scaling (MetaSettings *settings, diff --git a/src/backends/meta-settings.c b/src/backends/meta-settings.c index 262d75021..660c496a2 100644 --- a/src/backends/meta-settings.c +++ b/src/backends/meta-settings.c @@ -72,6 +72,9 @@ struct _MetaSettings GPtrArray *xwayland_grab_blacklist_patterns; MetaX11ScaleMode x11_scale_mode; + + /* Whether Xwayland should allow X11 clients from different endianess */ + gboolean xwayland_allow_byte_swapped_clients; }; G_DEFINE_TYPE (MetaSettings, meta_settings, G_TYPE_OBJECT) @@ -498,6 +501,15 @@ update_xwayland_allow_grabs (MetaSettings *settings) "xwayland-allow-grabs"); } +static void +update_xwayland_allow_byte_swapped_clients (MetaSettings *settings) +{ + + settings->xwayland_allow_byte_swapped_clients = + g_settings_get_flags (settings->wayland_settings, + "xwayland-allow-byte-swapped-clients"); +} + static void wayland_settings_changed (GSettings *wayland_settings, gchar *key, @@ -512,6 +524,10 @@ wayland_settings_changed (GSettings *wayland_settings, { update_xwayland_grab_access_rules (settings); } + else if (g_str_equal (key, "xwayland-allow-byte-swapped-clients")) + { + update_xwayland_allow_byte_swapped_clients (settings); + } } static void @@ -541,6 +557,12 @@ meta_settings_are_xwayland_grabs_allowed (MetaSettings *settings) return (settings->xwayland_allow_grabs); } +gboolean +meta_settings_are_xwayland_byte_swapped_clients_allowed (MetaSettings *settings) +{ + return settings->xwayland_allow_byte_swapped_clients; +} + MetaX11ScaleMode meta_settings_get_x11_scale_mode (MetaSettings *settings) { diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c index 2917912c0..491d65af7 100644 --- a/src/wayland/meta-xwayland.c +++ b/src/wayland/meta-xwayland.c @@ -580,6 +580,10 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager, GSubprocessFlags flags; GError *error = NULL; g_autoptr (GTask) task = NULL; + MetaBackend *backend; + MetaSettings *settings; + const char *args[32]; + int i; task = g_task_new (NULL, cancellable, callback, user_data); g_task_set_source_tag (task, meta_xwayland_start_xserver); @@ -614,6 +618,9 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager, flags |= G_SUBPROCESS_FLAGS_STDERR_SILENCE; } + backend = meta_get_backend (); + settings = meta_backend_get_settings (backend); + launcher = g_subprocess_launcher_new (flags); g_subprocess_launcher_take_fd (launcher, xwayland_client_fd[1], 3); @@ -624,23 +631,40 @@ 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 + +#ifdef HAVE_XWAYLAND_BYTE_SWAPPED_CLIENTS + if (meta_settings_are_xwayland_byte_swapped_clients_allowed (settings)) + args[i++] = "+byteswappedclients"; + else + args[i++] = "-byteswappedclients"; #endif - NULL); + + /* Terminator */ + args[i++] = NULL; + + manager->proc = g_subprocess_launcher_spawnv (launcher, args, &error); if (!manager->proc) {