#include "xwayland-shell-v1-protocol.h"
#endif
#include "drm-lease-v1-protocol.h"
+#include "common/macros.h"
#include "config/rcxml.h"
#include "config/session.h"
#include "decorations.h"
}
}
+static bool
+protocol_is_privileged(const struct wl_interface *iface)
+{
+ static const char * const rejected[] = {
+ "wp_drm_lease_device_v1",
+ "zwlr_gamma_control_manager_v1",
+ "zwlr_output_manager_v1",
+ "zwlr_output_power_manager_v1",
+ "zwp_input_method_manager_v2",
+ "zwlr_virtual_pointer_manager_v1",
+ "zwp_virtual_keyboard_manager_v1",
+ "zwlr_export_dmabuf_manager_v1",
+ "zwlr_screencopy_manager_v1",
+ "zwlr_data_control_manager_v1",
+ "wp_security_context_manager_v1",
+ "ext_idle_notifier_v1",
+ "zcosmic_workspace_manager_v1",
+ "zwlr_foreign_toplevel_manager_v1",
+ "ext_foreign_toplevel_list_v1",
+ "ext_session_lock_manager_v1",
+ "zwlr_layer_shell_v1",
+ };
+ for (size_t i = 0; i < ARRAY_SIZE(rejected); i++) {
+ if (!strcmp(iface->name, rejected[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+allow_for_sandbox(const struct wlr_security_context_v1_state *security_state,
+ const struct wl_interface *iface)
+{
+ if (!strcmp(iface->name, "security_context_manager_v1")) {
+ return false;
+ }
+
+ /* protocols are split into 3 blocks, from least privileges to highest privileges */
+ static const char * const allowed_protocols[] = {
+ /* absolute base */
+ "wl_shm",
+ "wl_compositor",
+ "wl_subcompositor",
+ "wl_data_device_manager", /* would be great if we could drop this one */
+ "wl_seat",
+ "xdg_wm_base",
+ /* enhanced */
+ "wl_output",
+ "wl_drm",
+ "zwp_linux_dmabuf_v1",
+ "zwp_primary_selection_device_manager_v1",
+ "zwp_text_input_manager_v3",
+ "zwp_pointer_gestures_v1",
+ "wp_cursor_shape_manager_v1",
+ "zwp_relative_pointer_manager_v1",
+ "xdg_activation_v1",
+ "org_kde_kwin_server_decoration_manager",
+ "zxdg_decoration_manager_v1",
+ "wp_presentation",
+ "wp_viewporter",
+ "wp_single_pixel_buffer_manager_v1",
+ "wp_fractional_scale_manager_v1",
+ "wp_tearing_control_manager_v1",
+ "zwp_tablet_manager_v2",
+ /* plus */
+ "zwp_idle_inhibit_manager_v1",
+ "zwp_pointer_constraints_v1",
+ "zxdg_output_manager_v1",
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(allowed_protocols); i++) {
+ if (!strcmp(iface->name, allowed_protocols[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
static bool
server_global_filter(const struct wl_client *client, const struct wl_global *global, void *data)
{
wlr_security_context_manager_v1_lookup_client(
server->security_context_manager_v1, (struct wl_client *)client);
if (security_context && global == server->security_context_manager_v1->global) {
- wlr_log(WLR_DEBUG, "blocking security_context_manager_v1 for the sandboxed client");
return false;
+ } else if (security_context) {
+ /*
+ * We are using an allow list for sandboxes to not
+ * accidentally leak a new privileged protocol.
+ */
+ bool allow = allow_for_sandbox(security_context, iface);
+ /*
+ * TODO: The following call is basically useless right now
+ * and should be replaced with
+ * assert(allow || protocol_is_privileged(iface));
+ * This ensures that our lists are in sync with what
+ * protocols labwc supports.
+ */
+ if (!allow && !protocol_is_privileged(iface)) {
+ 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",
+ iface->name, security_context->sandbox_engine,
+ security_context->app_id, security_context->instance_id);
+ }
+ return allow;
}
return true;