From 26cd95ebfd3ded184080aaf188b8be69a6b8bb80 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Thu, 18 Sep 2025 12:49:45 +0200 Subject: [PATCH 1/6] allow to reuse set_cloexec --- include/common/spawn.h | 7 +++++++ src/common/spawn.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/common/spawn.h b/include/common/spawn.h index 43123269..3f766eff 100644 --- a/include/common/spawn.h +++ b/include/common/spawn.h @@ -2,8 +2,15 @@ #ifndef LABWC_SPAWN_H #define LABWC_SPAWN_H +#include #include +/** + * set_cloexec - set file descriptor to close on exit + * @fd: file descriptor + */ +bool set_cloexec(int fd); + /** * spawn_primary_client - execute asynchronously * @command: command to be executed diff --git a/src/common/spawn.c b/src/common/spawn.c index 898c4800..9468b2b9 100644 --- a/src/common/spawn.c +++ b/src/common/spawn.c @@ -24,7 +24,7 @@ reset_signals_and_limits(void) signal(SIGPIPE, SIG_DFL); } -static bool +bool set_cloexec(int fd) { int flags = fcntl(fd, F_GETFD); From 589ea47920b85fcfdefad5b04cdff562e7f11360 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Sat, 6 Sep 2025 10:43:26 +0200 Subject: [PATCH 2/6] implement permission infrastructure --- include/permissions.h | 11 ++++++ src/meson.build | 1 + src/permissions.c | 81 +++++++++++++++++++++++++++++++++++++++++++ src/server.c | 6 ++-- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 include/permissions.h create mode 100644 src/permissions.c diff --git a/include/permissions.h b/include/permissions.h new file mode 100644 index 00000000..77d46762 --- /dev/null +++ b/include/permissions.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LABWC_PERMISSIONS_H +#define LABWC_PERMISSIONS_H + +#include +#include + +int permissions_context_create(struct wl_display *display, uint32_t permissions); +bool permissions_check(const struct wl_client *client, const struct wl_interface *iface); + +#endif diff --git a/src/meson.build b/src/meson.build index 40ec3170..27056552 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,6 +1,7 @@ labwc_sources = files( 'action.c', 'buffer.c', + 'permissions.c', 'debug.c', 'desktop.c', 'dnd.c', diff --git a/src/permissions.c b/src/permissions.c new file mode 100644 index 00000000..df7c3f50 --- /dev/null +++ b/src/permissions.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0-only +#define _POSIX_C_SOURCE 200809L +#include "permissions.h" +#include +#include +#include +#include +#include "common/mem.h" +#include "common/spawn.h" +#include "config/rcxml.h" + +struct permissions_context { + uint32_t permissions; + int fd; + struct wl_listener destroy; +}; + +static void +permissions_context_handle_destroy(struct wl_listener *listener, void *data) +{ + struct permissions_context *context = wl_container_of(listener, context, destroy); + close(context->fd); + zfree(context); +} + +static uint32_t +permissions_get(const struct wl_client *client) +{ + struct wl_listener *listener = wl_client_get_destroy_listener( + (struct wl_client *)client, permissions_context_handle_destroy); + if (!listener) { + return 0; + } + + struct permissions_context *context = wl_container_of(listener, context, destroy); + return context->permissions; +} + +int +permissions_context_create(struct wl_display *display, uint32_t permissions) +{ + if (permissions == 0) { + return -1; + } + + int sv[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) != 0) { + wlr_log_errno(WLR_ERROR, "socketpair failed"); + return -1; + } + + if (!set_cloexec(sv[0])) { + close(sv[0]); + close(sv[1]); + return -1; + } + + struct wl_client *client = wl_client_create(display, sv[0]); + if (!client) { + wlr_log(WLR_ERROR, "failed to create client"); + close(sv[0]); + close(sv[1]); + return -1; + } + + struct permissions_context *context = znew(*context); + context->permissions = permissions; + context->fd = sv[0]; + context->destroy.notify = permissions_context_handle_destroy; + wl_client_add_destroy_listener(client, &context->destroy); + + return sv[1]; +} + +bool +permissions_check(const struct wl_client *client, const struct wl_interface *iface) +{ + uint32_t permissions = permissions_get(client) | rc.allowed_interfaces; + uint32_t required = parse_privileged_interface(iface->name); + return (permissions & required) == required; +} diff --git a/src/server.c b/src/server.c index e4b27026..767ca8d6 100644 --- a/src/server.c +++ b/src/server.c @@ -66,6 +66,7 @@ #include "menu/menu.h" #include "output.h" #include "output-virtual.h" +#include "permissions.h" #include "regions.h" #include "resize-indicator.h" #include "scaled-buffer/scaled-buffer.h" @@ -294,8 +295,7 @@ server_global_filter(const struct wl_client *client, const struct wl_global *glo } #endif - uint32_t iface_id = parse_privileged_interface(iface->name); - if (iface_id && !(iface_id & rc.allowed_interfaces)) { + if (!permissions_check(client, iface)) { return false; } @@ -318,7 +318,7 @@ server_global_filter(const struct wl_client *client, const struct wl_global *glo * This ensures that our lists are in sync with what * protocols labwc supports. */ - if (!allow && !iface_id) { + if (!allow && !parse_privileged_interface(iface->name)) { wlr_log(WLR_ERROR, "Blocking unknown protocol %s", iface->name); } else if (!allow) { wlr_log(WLR_DEBUG, "Blocking %s for security context %s->%s->%s", From bed325a7ffa4476bf2907fad8e73aeb5900357c1 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Sat, 6 Sep 2025 10:44:13 +0200 Subject: [PATCH 3/6] add permissions to actions --- include/action.h | 1 + include/common/spawn.h | 2 +- src/action.c | 12 +++++++++++- src/common/spawn.c | 12 +++++++++++- src/config/session.c | 6 +++--- src/main.c | 2 +- 6 files changed, 28 insertions(+), 7 deletions(-) diff --git a/include/action.h b/include/action.h index b09aa35c..c767b445 100644 --- a/include/action.h +++ b/include/action.h @@ -18,6 +18,7 @@ struct action { */ uint32_t type; /* enum action_type */ + uint32_t allowed_interfaces; struct wl_list args; /* struct action_arg.link */ }; diff --git a/include/common/spawn.h b/include/common/spawn.h index 3f766eff..9145c727 100644 --- a/include/common/spawn.h +++ b/include/common/spawn.h @@ -21,7 +21,7 @@ pid_t spawn_primary_client(const char *command); * spawn_async_no_shell - execute asynchronously * @command: command to be executed */ -void spawn_async_no_shell(char const *command); +void spawn_async_no_shell(char const *command, int socket_fd); /** * spawn_piped - execute asynchronously diff --git a/src/action.c b/src/action.c index 2cfa6be6..35537b8b 100644 --- a/src/action.c +++ b/src/action.c @@ -27,6 +27,7 @@ #include "menu/menu.h" #include "output.h" #include "output-virtual.h" +#include "permissions.h" #include "regions.h" #include "ssd.h" #include "theme.h" @@ -302,6 +303,9 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char if (!strcmp(argument, "command") || !strcmp(argument, "execute")) { action_arg_add_str(action, "command", content); goto cleanup; + } else if (!strcmp(argument, "allow")) { + action->allowed_interfaces |= parse_privileged_interface(content); + goto cleanup; } break; case ACTION_TYPE_MOVE_TO_EDGE: @@ -570,6 +574,7 @@ action_create(const char *action_name) struct action *action = znew(*action); action->type = action_type; + action->allowed_interfaces = 0; wl_list_init(&action->args); return action; } @@ -1077,7 +1082,12 @@ run_action(struct view *view, struct action *action, struct buf cmd = BUF_INIT; buf_add(&cmd, action_get_str(action, "command", NULL)); buf_expand_tilde(&cmd); - spawn_async_no_shell(cmd.data); + int socket_fd = -1; + if (action->allowed_interfaces) { + socket_fd = permissions_context_create( + server.wl_display, action->allowed_interfaces); + } + spawn_async_no_shell(cmd.data, socket_fd); buf_reset(&cmd); break; } diff --git a/src/common/spawn.c b/src/common/spawn.c index 9468b2b9..1cb4dadd 100644 --- a/src/common/spawn.c +++ b/src/common/spawn.c @@ -43,10 +43,11 @@ set_cloexec(int fd) } void -spawn_async_no_shell(char const *command) +spawn_async_no_shell(char const *command, int socket_fd) { GError *err = NULL; gchar **argv = NULL; + char socket_str[32]; assert(command); @@ -73,6 +74,12 @@ spawn_async_no_shell(char const *command) reset_signals_and_limits(); setsid(); + if (socket_fd != -1) { + snprintf(socket_str, sizeof(socket_str), "%d", socket_fd); + if (setenv("WAYLAND_SOCKET", socket_str, 1) != 0) { + wlr_log(WLR_ERROR, "unable to setenv() WAYLAND_SOCKET"); + } + } grandchild = fork(); if (grandchild == 0) { execvp(argv[0], argv); @@ -84,6 +91,9 @@ spawn_async_no_shell(char const *command) default: break; } + if (socket_fd != -1) { + close(socket_fd); + } waitpid(child, NULL, 0); out: g_strfreev(argv); diff --git a/src/config/session.c b/src/config/session.c index 7df6236c..cf1b69c0 100644 --- a/src/config/session.c +++ b/src/config/session.c @@ -219,12 +219,12 @@ execute_update(const char *env_keys, const char *env_unset_keys, bool initialize char *cmd = strdup_printf("dbus-update-activation-environment %s", initialize ? env_keys : env_unset_keys); - spawn_async_no_shell(cmd); + spawn_async_no_shell(cmd, -1); free(cmd); cmd = strdup_printf("systemctl --user %s %s", initialize ? "import-environment" : "unset-environment", env_keys); - spawn_async_no_shell(cmd); + spawn_async_no_shell(cmd, -1); free(cmd); } @@ -320,7 +320,7 @@ session_run_script(const char *script) } wlr_log(WLR_INFO, "run session script %s", path->string); char *cmd = strdup_printf("sh %s", path->string); - spawn_async_no_shell(cmd); + spawn_async_no_shell(cmd, -1); free(cmd); if (!should_merge_config) { diff --git a/src/main.c b/src/main.c index 373f4480..83fee58f 100644 --- a/src/main.c +++ b/src/main.c @@ -153,7 +153,7 @@ idle_callback(void *data) session_autostart_init(); if (ctx->startup_cmd) { - spawn_async_no_shell(ctx->startup_cmd); + spawn_async_no_shell(ctx->startup_cmd, -1); } } From f0a9875da605c8899c8a7a225527a22a83052d05 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Sat, 6 Sep 2025 12:46:52 +0200 Subject: [PATCH 4/6] add autostart with permissions --- include/config/rcxml.h | 2 ++ src/config/rcxml.c | 3 +++ src/config/session.c | 9 +++++++++ 3 files changed, 14 insertions(+) diff --git a/include/config/rcxml.h b/include/config/rcxml.h index 8a2c606c..c20a901d 100644 --- a/include/config/rcxml.h +++ b/include/config/rcxml.h @@ -202,6 +202,8 @@ struct rcxml { struct wl_list window_rules; /* struct window_rule.link */ + struct wl_list autostart; /* struct action.link */ + /* Menu */ unsigned int menu_ignore_button_release_period; bool menu_show_icons; diff --git a/src/config/rcxml.c b/src/config/rcxml.c index 9884d15e..493911b9 100644 --- a/src/config/rcxml.c +++ b/src/config/rcxml.c @@ -1083,6 +1083,8 @@ entry(xmlNode *node, char *nodename, char *content) /* handle nested nodes */ if (!strcasecmp(nodename, "margin")) { fill_usable_area_override(node); + } else if (!strcasecmp(nodename, "autostart")) { + append_parsed_actions(node, &rc.autostart); } else if (!strcasecmp(nodename, "keybind.keyboard")) { fill_keybind(node); } else if (!strcasecmp(nodename, "context.mouse")) { @@ -1477,6 +1479,7 @@ rcxml_init(void) if (!has_run) { wl_list_init(&rc.usable_area_overrides); + wl_list_init(&rc.autostart); wl_list_init(&rc.keybinds); wl_list_init(&rc.mousebinds); wl_list_init(&rc.libinput_categories); diff --git a/src/config/session.c b/src/config/session.c index cf1b69c0..52b39ff2 100644 --- a/src/config/session.c +++ b/src/config/session.c @@ -11,6 +11,7 @@ #include #include #include +#include "action.h" #include "common/buf.h" #include "common/dir.h" #include "common/file-helpers.h" @@ -303,6 +304,13 @@ session_environment_init(void) paths_destroy(&paths); } +static void +session_run_rc_autostart(void) +{ + wlr_log(WLR_INFO, "run autostart actions"); + actions_run(NULL, &rc.autostart, NULL); +} + void session_run_script(const char *script) { @@ -335,6 +343,7 @@ session_autostart_init(void) { /* Update dbus and systemd user environment, each may fail gracefully */ update_activation_env(/* initialize */ true); + session_run_rc_autostart(); session_run_script("autostart"); } From 2285c5e77c39027ee8a87585710a5685790090ce Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Sat, 28 Feb 2026 11:58:30 +0100 Subject: [PATCH 5/6] implement permissions_context_clone() --- include/permissions.h | 1 + src/permissions.c | 39 ++++++++++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/include/permissions.h b/include/permissions.h index 77d46762..c7136974 100644 --- a/include/permissions.h +++ b/include/permissions.h @@ -6,6 +6,7 @@ #include int permissions_context_create(struct wl_display *display, uint32_t permissions); +bool permissions_context_clone(struct wl_client *client, int fd); bool permissions_check(const struct wl_client *client, const struct wl_interface *iface); #endif diff --git a/src/permissions.c b/src/permissions.c index df7c3f50..0c744a63 100644 --- a/src/permissions.c +++ b/src/permissions.c @@ -36,6 +36,24 @@ permissions_get(const struct wl_client *client) return context->permissions; } +static bool +context_create(struct wl_display *display, uint32_t permissions, int fd) +{ + struct wl_client *client = wl_client_create(display, fd); + if (!client) { + wlr_log(WLR_ERROR, "failed to create client"); + return false; + } + + struct permissions_context *context = znew(*context); + context->permissions = permissions; + context->fd = fd; + context->destroy.notify = permissions_context_handle_destroy; + wl_client_add_destroy_listener(client, &context->destroy); + + return true; +} + int permissions_context_create(struct wl_display *display, uint32_t permissions) { @@ -55,23 +73,26 @@ permissions_context_create(struct wl_display *display, uint32_t permissions) return -1; } - struct wl_client *client = wl_client_create(display, sv[0]); - if (!client) { - wlr_log(WLR_ERROR, "failed to create client"); + if (!context_create(display, permissions, sv[0])) { close(sv[0]); close(sv[1]); return -1; } - struct permissions_context *context = znew(*context); - context->permissions = permissions; - context->fd = sv[0]; - context->destroy.notify = permissions_context_handle_destroy; - wl_client_add_destroy_listener(client, &context->destroy); - return sv[1]; } +bool +permissions_context_clone(struct wl_client *client, int fd) +{ + struct wl_display *display = wl_client_get_display(client); + uint32_t permissions = permissions_get(client); + if (permissions == 0) { + return false; + } + return context_create(display, permissions, fd); +} + bool permissions_check(const struct wl_client *client, const struct wl_interface *iface) { From d212c11572ea23dfa797bc9380417333a8803c56 Mon Sep 17 00:00:00 2001 From: Tobias Bengfort Date: Sat, 28 Feb 2026 11:47:14 +0100 Subject: [PATCH 6/6] add socket manager protocol --- include/labwc.h | 1 + include/protocols/ext_socket_manager_v1.h | 21 +++++ protocols/ext-socket-manager-unstable-v1.xml | 51 +++++++++++++ protocols/meson.build | 1 + src/meson.build | 1 + .../ext_socket_manager_v1.c | 76 +++++++++++++++++++ src/protocols/ext-socket-manager/meson.build | 3 + src/protocols/meson.build | 1 + src/server.c | 4 + 9 files changed, 159 insertions(+) create mode 100644 include/protocols/ext_socket_manager_v1.h create mode 100644 protocols/ext-socket-manager-unstable-v1.xml create mode 100644 src/protocols/ext-socket-manager/ext_socket_manager_v1.c create mode 100644 src/protocols/ext-socket-manager/meson.build create mode 100644 src/protocols/meson.build diff --git a/include/labwc.h b/include/labwc.h index 511fdd65..a0dc7fa3 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -298,6 +298,7 @@ struct server { struct wlr_tablet_manager_v2 *tablet_manager; struct wlr_security_context_manager_v1 *security_context_manager_v1; + struct ext_socket_manager_v1 *ext_socket_manager_v1; /* Set when in cycle (alt-tab) mode */ struct cycle_state cycle; diff --git a/include/protocols/ext_socket_manager_v1.h b/include/protocols/ext_socket_manager_v1.h new file mode 100644 index 00000000..22dab9be --- /dev/null +++ b/include/protocols/ext_socket_manager_v1.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef LABWC_PROTOCOLS_EXT_SOCKET_MANAGER_H +#define LABWC_PROTOCOLS_EXT_SOCKET_MANAGER_H + +#include + +struct ext_socket_manager_v1 { + struct wl_global *global; + + struct { + struct wl_signal destroy; + struct wl_signal register_socket; + } events; + + struct wl_listener display_destroy; +}; + +struct ext_socket_manager_v1 *ext_socket_manager_v1_create( + struct wl_display *display); + +#endif diff --git a/protocols/ext-socket-manager-unstable-v1.xml b/protocols/ext-socket-manager-unstable-v1.xml new file mode 100644 index 00000000..82be66cf --- /dev/null +++ b/protocols/ext-socket-manager-unstable-v1.xml @@ -0,0 +1,51 @@ + + + + Copyright © 2026 Tobias Bengfort + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + If a client has received a privileged socket via WAYLAND_SOCKET, it can + use this interface to register additional privileged sockets to pass to + child processes. + + + + + Destroy the manager. This doesn't destroy objects created with the + manager. + + + + + + Registers a new socket with the same privileges as the current one. + The socket must be created by the client. After registraton, it can then + be passed to a child process via WAYLAND_SOCKET. + + + + + diff --git a/protocols/meson.build b/protocols/meson.build index 928bd601..c28f693b 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -16,6 +16,7 @@ wayland_scanner_server = generator( server_protocols = [ 'wlr-layer-shell-unstable-v1.xml', 'wlr-output-power-management-unstable-v1.xml', + 'ext-socket-manager-unstable-v1.xml', ] server_protos_src = [] diff --git a/src/meson.build b/src/meson.build index 27056552..dfd23a52 100644 --- a/src/meson.build +++ b/src/meson.build @@ -56,5 +56,6 @@ subdir('foreign-toplevel') subdir('img') subdir('input') subdir('menu') +subdir('protocols') subdir('scaled-buffer') subdir('ssd') diff --git a/src/protocols/ext-socket-manager/ext_socket_manager_v1.c b/src/protocols/ext-socket-manager/ext_socket_manager_v1.c new file mode 100644 index 00000000..9b833e90 --- /dev/null +++ b/src/protocols/ext-socket-manager/ext_socket_manager_v1.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include "permissions.h" +#include "ext-socket-manager-unstable-v1-protocol.h" + +#define EXT_SOCKET_MANAGER_V1_VERSION 1 + +static void +manager_handle_destroy(struct wl_client *client, struct wl_resource *resource) +{ + wl_resource_destroy(resource); +} + +static void +manager_handle_register_socket(struct wl_client *client, + struct wl_resource *manager_resource, int fd) +{ + permissions_context_clone(client, fd); +} + +static const struct ext_socket_manager_v1_interface manager_impl = { + .destroy = manager_handle_destroy, + .register_socket = manager_handle_register_socket, +}; + +static void +manager_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id) +{ + struct ext_socket_manager_v1 *manager = data; + + struct wl_resource *resource = + wl_resource_create(client, &ext_socket_manager_v1_interface, version, id); + if (!resource) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &manager_impl, manager, NULL); +} + +static void +handle_display_destroy(struct wl_listener *listener, void *data) +{ + struct ext_socket_manager_v1 *manager = + wl_container_of(listener, manager, display_destroy); + wl_signal_emit_mutable(&manager->events.destroy, manager); + + wl_global_destroy(manager->global); + wl_list_remove(&manager->display_destroy.link); + free(manager); +} + +struct ext_socket_manager_v1 * +ext_socket_manager_v1_create(struct wl_display *display) +{ + struct ext_socket_manager_v1 *manager = calloc(1, sizeof(*manager)); + if (!manager) { + return NULL; + } + + manager->global = wl_global_create(display, + &ext_socket_manager_v1_interface, + EXT_SOCKET_MANAGER_V1_VERSION, manager, manager_bind); + if (!manager->global) { + free(manager); + return NULL; + } + + wl_signal_init(&manager->events.destroy); + wl_signal_init(&manager->events.register_socket); + + manager->display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(display, &manager->display_destroy); + + return manager; +} diff --git a/src/protocols/ext-socket-manager/meson.build b/src/protocols/ext-socket-manager/meson.build new file mode 100644 index 00000000..5922e64e --- /dev/null +++ b/src/protocols/ext-socket-manager/meson.build @@ -0,0 +1,3 @@ +labwc_sources += files( + 'ext_socket_manager_v1.c', +) diff --git a/src/protocols/meson.build b/src/protocols/meson.build new file mode 100644 index 00000000..d42d84b4 --- /dev/null +++ b/src/protocols/meson.build @@ -0,0 +1 @@ +subdir('ext-socket-manager') diff --git a/src/server.c b/src/server.c index 767ca8d6..aee12905 100644 --- a/src/server.c +++ b/src/server.c @@ -76,6 +76,7 @@ #include "view.h" #include "workspaces.h" #include "xwayland.h" +#include "protocols/ext_socket_manager_v1.h" #define LAB_EXT_DATA_CONTROL_VERSION 1 #define LAB_EXT_FOREIGN_TOPLEVEL_LIST_VERSION 1 @@ -263,6 +264,7 @@ allow_for_sandbox(const struct wlr_security_context_v1_state *security_state, "zwp_idle_inhibit_manager_v1", "zwp_pointer_constraints_v1", "zxdg_output_manager_v1", + "ext_socket_manager_v1", }; for (size_t i = 0; i < ARRAY_SIZE(allowed_protocols); i++) { @@ -688,6 +690,8 @@ server_init(void) LAB_EXT_DATA_CONTROL_VERSION); server.security_context_manager_v1 = wlr_security_context_manager_v1_create(server.wl_display); + server.ext_socket_manager_v1 = + ext_socket_manager_v1_create(server.wl_display); wlr_viewporter_create(server.wl_display); wlr_single_pixel_buffer_manager_v1_create(server.wl_display); wlr_fractional_scale_manager_v1_create(server.wl_display,