Skip to content

Commit

Permalink
common: add support for Wayland security context
Browse files Browse the repository at this point in the history
This exposes a reliable way for Wayland compositors to get
identifying information about a client. Compositors can then
apply security policies if desirable.

See: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/68
  • Loading branch information
emersion committed Jul 4, 2023
1 parent 532f36d commit 6010dc1
Show file tree
Hide file tree
Showing 13 changed files with 281 additions and 31 deletions.
4 changes: 3 additions & 1 deletion app/flatpak-builtins-build.c
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,7 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
g_autofree char *runtime_extensions = NULL;
g_autofree char *runtime_ld_path = NULL;
g_autofree char *instance_id_host_dir = NULL;
g_autofree char *instance_id = NULL;
char pid_str[64];
g_autofree char *pid_path = NULL;
g_autoptr(GFile) app_id_dir = NULL;
Expand Down Expand Up @@ -549,12 +550,13 @@ flatpak_builtin_build (int argc, char **argv, GCancellable *cancellable, GError
FALSE, TRUE, TRUE,
&app_info_path, -1,
&instance_id_host_dir,
&instance_id,
error))
return FALSE;

if (!flatpak_run_add_environment_args (bwrap, app_info_path, run_flags, id,
app_context, app_id_dir, NULL, -1,
NULL, cancellable, error))
instance_id, NULL, cancellable, error))
return FALSE;

for (i = 0; opt_bind_mounts != NULL && opt_bind_mounts[i] != NULL; i++)
Expand Down
15 changes: 15 additions & 0 deletions common/Makefile.am.inc
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,21 @@ common/flatpak-systemd-dbus-generated.c: data/org.freedesktop.systemd1.xml Makef
common/%-dbus-generated.h: common/%-dbus-generated.c
@true # Built as a side-effect of the rules for the .c

if ENABLE_WAYLAND_SECURITY_CONTEXT
wayland_built_sources = common/security-context-v1-protocol.c common/security-context-v1-protocol.h
endif

wl_security_context_xml = $(WAYLAND_PROTOCOLS_DATADIR)/staging/security-context/security-context-v1.xml

common/security-context-v1-protocol.c: $(wl_security_context_xml)
$(AM_V_GEN) $(WAYLAND_SCANNER) code $(wl_security_context_xml) $(builddir)/common/security-context-v1-protocol.c

common/security-context-v1-protocol.h: $(wl_security_context_xml)
$(AM_V_GEN) $(WAYLAND_SCANNER) client-header $(wl_security_context_xml) $(builddir)/common/security-context-v1-protocol.h

nodist_libflatpak_common_base_la_SOURCES = \
$(dbus_built_sources) \
$(wayland_built_sources) \
$(NULL)

BUILT_SOURCES += $(nodist_libflatpak_common_base_la_SOURCES)
Expand Down Expand Up @@ -219,6 +232,7 @@ libflatpak_common_la_CFLAGS = \
$(SOUP_CFLAGS) \
$(SYSTEMD_CFLAGS) \
$(XAUTH_CFLAGS) \
$(WAYLAND_CLIENT_CFLAGS) \
$(XML_CFLAGS) \
$(NULL)
libflatpak_common_la_LIBADD = \
Expand All @@ -237,6 +251,7 @@ libflatpak_common_la_LIBADD = \
$(SOUP_LIBS) \
$(SYSTEMD_LIBS) \
$(XAUTH_LIBS) \
$(WAYLAND_CLIENT_LIBS) \
$(XML_LIBS) \
$(NULL)
Expand Down
2 changes: 1 addition & 1 deletion common/flatpak-dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -8345,7 +8345,7 @@ apply_extra_data (FlatpakDir *self,

if (!flatpak_run_add_environment_args (bwrap, NULL, run_flags, id,
app_context, NULL, NULL, -1,
NULL, cancellable, error))
NULL, NULL, cancellable, error))
return FALSE;

flatpak_bwrap_populate_runtime_dir (bwrap, NULL);
Expand Down
2 changes: 2 additions & 0 deletions common/flatpak-run-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ gboolean flatpak_run_add_environment_args (FlatpakBwrap *bwrap,
GFile *app_id_dir,
GPtrArray *previous_app_id_dirs,
int per_app_dir_lock_fd,
const char *instance_id,
FlatpakExports **exports_out,
GCancellable *cancellable,
GError **error);
Expand Down Expand Up @@ -177,6 +178,7 @@ gboolean flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
char **app_info_path_out,
int instance_id_fd,
char **host_instance_id_host_dir_out,
char **instance_id_out,
GError **error);

gboolean flatpak_run_app (FlatpakDecomposed *app_ref,
Expand Down
4 changes: 3 additions & 1 deletion common/flatpak-run-sockets-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ G_BEGIN_DECLS

void flatpak_run_add_socket_args_environment (FlatpakBwrap *bwrap,
FlatpakContextShares shares,
FlatpakContextSockets sockets);
FlatpakContextSockets sockets,
const char *app_id,
const char *instance_id);
void flatpak_run_add_socket_args_late (FlatpakBwrap *bwrap,
FlatpakContextShares shares);

Expand Down
11 changes: 7 additions & 4 deletions common/flatpak-run-sockets.c
Original file line number Diff line number Diff line change
Expand Up @@ -170,17 +170,20 @@ flatpak_run_add_ssh_args (FlatpakBwrap *bwrap)
* use of a proxy.
*/
void
flatpak_run_add_socket_args_environment (FlatpakBwrap *bwrap,
FlatpakContextShares shares,
FlatpakContextSockets sockets)
flatpak_run_add_socket_args_environment (FlatpakBwrap *bwrap,
FlatpakContextShares shares,
FlatpakContextSockets sockets,
const char *app_id,
const char *instance_id)
{
gboolean has_wayland = FALSE;
gboolean allow_x11;

if (sockets & FLATPAK_CONTEXT_SOCKET_WAYLAND)
{
g_info ("Allowing wayland access");
has_wayland = flatpak_run_add_wayland_args (bwrap);
g_assert (app_id && instance_id);
has_wayland = flatpak_run_add_wayland_args (bwrap, app_id, instance_id);
}

if ((sockets & FLATPAK_CONTEXT_SOCKET_FALLBACK_X11) != 0)
Expand Down
4 changes: 3 additions & 1 deletion common/flatpak-run-wayland-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
G_BEGIN_DECLS

gboolean
flatpak_run_add_wayland_args (FlatpakBwrap *bwrap);
flatpak_run_add_wayland_args (FlatpakBwrap *bwrap,
const char *app_id,
const char *instance_id);

G_END_DECLS
152 changes: 151 additions & 1 deletion common/flatpak-run-wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,156 @@
#include "config.h"
#include "flatpak-run-wayland-private.h"

#ifdef ENABLE_WAYLAND_SECURITY_CONTEXT
#include <sys/socket.h>
#include <sys/un.h>
#include <wayland-client.h>
#include "security-context-v1-protocol.h"
#endif

#include "flatpak-utils-private.h"

#ifdef ENABLE_WAYLAND_SECURITY_CONTEXT

static void registry_handle_global (void *data, struct wl_registry *registry,
uint32_t name, const char *interface,
uint32_t version)
{
struct wp_security_context_manager_v1 **out = data;

if (strcmp (interface, wp_security_context_manager_v1_interface.name) == 0) {
*out = wl_registry_bind (registry, name,
&wp_security_context_manager_v1_interface, 1);
}
}

static void registry_handle_global_remove (void *data,
struct wl_registry *registry,
uint32_t name)
{
/* no-op */
}

static const struct wl_registry_listener registry_listener = {
.global = registry_handle_global,
.global_remove = registry_handle_global_remove,
};

static char *
create_wl_socket (char *template)
{
g_autofree char *user_runtime_dir = flatpak_get_real_xdg_runtime_dir ();
g_autofree char *proxy_socket_dir = g_build_filename (user_runtime_dir, ".flatpak/wl", NULL);
g_autofree char *proxy_socket = g_build_filename (proxy_socket_dir, template, NULL);
int fd;

if (!glnx_shutil_mkdir_p_at (AT_FDCWD, proxy_socket_dir, 0755, NULL, NULL))
return NULL;

fd = g_mkstemp (proxy_socket);
if (fd == -1)
return NULL;

close (fd);

return g_steal_pointer (&proxy_socket);
}

static gboolean
flatpak_run_add_wayland_security_context_args (FlatpakBwrap *bwrap,
const char *app_id,
const char *instance_id,
gboolean *available_out)
{
gboolean res = FALSE;
struct wl_display *display;
struct wl_registry *registry;
struct wp_security_context_manager_v1 *security_context_manager = NULL;
struct wp_security_context_v1 *security_context;
struct sockaddr_un sockaddr = {0};
g_autofree char *socket_path = NULL;
int listen_fd = -1, sync_fd, ret;

*available_out = TRUE;

display = wl_display_connect (NULL);
if (!display)
return FALSE;

registry = wl_display_get_registry (display);
wl_registry_add_listener (registry, &registry_listener,
&security_context_manager);
ret = wl_display_roundtrip (display);
wl_registry_destroy (registry);
if (ret < 0)
goto out;

if (!security_context_manager) {
*available_out = FALSE;
goto out;
}

socket_path = create_wl_socket ("wayland-XXXXXX");
if (!socket_path)
goto out;

unlink (socket_path);

listen_fd = socket (AF_UNIX, SOCK_STREAM, 0);
if (listen_fd < 0)
goto out;

sockaddr.sun_family = AF_UNIX;
snprintf (sockaddr.sun_path, sizeof(sockaddr.sun_path), "%s", socket_path);
if (bind (listen_fd, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) != 0)
goto out;

if (listen (listen_fd, 0) != 0)
goto out;

sync_fd = flatpak_bwrap_add_sync_fd (bwrap);
if (sync_fd < 0)
goto out;

security_context = wp_security_context_manager_v1_create_listener (security_context_manager,
listen_fd,
sync_fd);
wp_security_context_v1_set_sandbox_engine (security_context, "flatpak");
wp_security_context_v1_set_app_id (security_context, app_id);
wp_security_context_v1_set_instance_id (security_context, instance_id);
wp_security_context_v1_commit (security_context);
wp_security_context_v1_destroy (security_context);
if (wl_display_roundtrip (display) < 0)
goto out;

flatpak_bwrap_add_args (bwrap,
"--ro-bind", socket_path, "/run/flatpak/wayland-0",
NULL);
flatpak_bwrap_set_env (bwrap, "WAYLAND_DISPLAY", "/run/flatpak/wayland-0", TRUE);

res = TRUE;

out:
if (listen_fd >= 0)
close (listen_fd);
if (socket_path != )
if (security_context_manager)
wp_security_context_manager_v1_destroy (security_context_manager);
wl_display_disconnect (display);
return res;
}

#endif /* ENABLE_WAYLAND_SECURITY_CONTEXT */

/**
* flatpak_run_add_wayland_args:
*
* Returns: %TRUE if a Wayland socket was found.
*/
gboolean
flatpak_run_add_wayland_args (FlatpakBwrap *bwrap)
flatpak_run_add_wayland_args (FlatpakBwrap *bwrap,
const char *app_id,
const char *instance_id)
{
const char *wayland_display;
g_autofree char *user_runtime_dir = flatpak_get_real_xdg_runtime_dir ();
Expand All @@ -38,6 +179,15 @@ flatpak_run_add_wayland_args (FlatpakBwrap *bwrap)
gboolean res = FALSE;
struct stat statbuf;

#ifdef ENABLE_WAYLAND_SECURITY_CONTEXT
gboolean security_context_available = FALSE;
if (flatpak_run_add_wayland_security_context_args (bwrap, app_id, instance_id,
&security_context_available))
return TRUE;
if (security_context_available)
return FALSE;
#endif /* ENABLE_WAYLAND_SECURITY_CONTEXT */

wayland_display = g_getenv ("WAYLAND_DISPLAY");
if (!wayland_display)
wayland_display = "wayland-0";
Expand Down
12 changes: 9 additions & 3 deletions common/flatpak-run.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap,
GFile *app_id_dir,
GPtrArray *previous_app_id_dirs,
int per_app_dir_lock_fd,
const char *instance_id,
FlatpakExports **exports_out,
GCancellable *cancellable,
GError **error)
Expand Down Expand Up @@ -487,7 +488,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap,
flatpak_context_append_bwrap_filesystem (context, bwrap, app_id, app_id_dir,
exports, xdg_dirs_conf, home_access);

flatpak_run_add_socket_args_environment (bwrap, context->shares, context->sockets);
flatpak_run_add_socket_args_environment (bwrap, context->shares, context->sockets, app_id, instance_id);
flatpak_run_add_session_dbus_args (bwrap, proxy_arg_bwrap, context, flags, app_id);
flatpak_run_add_system_dbus_args (bwrap, proxy_arg_bwrap, context, flags);
flatpak_run_add_a11y_dbus_args (bwrap, proxy_arg_bwrap, context, flags);
Expand Down Expand Up @@ -1320,6 +1321,7 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
char **app_info_path_out,
int instance_id_fd,
char **instance_id_host_dir_out,
char **instance_id_out,
GError **error)
{
g_autofree char *info_path = NULL;
Expand Down Expand Up @@ -1558,6 +1560,9 @@ flatpak_run_add_app_info_args (FlatpakBwrap *bwrap,
if (instance_id_host_dir_out != NULL)
*instance_id_host_dir_out = g_steal_pointer (&instance_id_host_dir);

if (instance_id_out != NULL)
*instance_id_out = g_steal_pointer (&instance_id);

return TRUE;
}

Expand Down Expand Up @@ -2836,6 +2841,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
g_autofree char *app_info_path = NULL;
g_autofree char *app_ld_path = NULL;
g_autofree char *instance_id_host_dir = NULL;
g_autofree char *instance_id = NULL;
g_autoptr(FlatpakContext) app_context = NULL;
g_autoptr(FlatpakContext) overrides = NULL;
g_autoptr(FlatpakExports) exports = NULL;
Expand Down Expand Up @@ -3271,7 +3277,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,
runtime_ref, app_id_dir, app_context, extra_context,
sandboxed, FALSE, flags & FLATPAK_RUN_FLAG_DEVEL,
&app_info_path, instance_id_fd, &instance_id_host_dir,
error))
&instance_id, error))
return FALSE;

if (!sandboxed)
Expand Down Expand Up @@ -3301,7 +3307,7 @@ flatpak_run_app (FlatpakDecomposed *app_ref,

if (!flatpak_run_add_environment_args (bwrap, app_info_path, flags,
app_id, app_context, app_id_dir, previous_app_id_dirs,
per_app_dir_lock_fd,
per_app_dir_lock_fd, instance_id,
&exports, cancellable, error))
return FALSE;

Expand Down

0 comments on commit 6010dc1

Please sign in to comment.