Skip to content

Commit

Permalink
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.

References: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/68
  • Loading branch information
emersion committed Oct 5, 2022
1 parent 572ca79 commit c2823de
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 9 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ jobs:
run: |
mkdir _build
pushd _build
../configure --enable-internal-checks --enable-asan --disable-introspection --with-curl --with-system-bubblewrap --with-system-dbus-proxy
../configure --enable-internal-checks --enable-asan --disable-introspection --with-curl --with-system-bubblewrap --with-system-dbus-proxy --disable-wayland-security-context
popd
env:
CFLAGS: -O2 -Wp,-D_FORTIFY_SOURCE=2
Expand Down Expand Up @@ -130,7 +130,7 @@ jobs:
run: |
mkdir _build
pushd _build
../configure --enable-internal-checks --enable-asan --disable-introspection --without-curl
../configure --enable-internal-checks --enable-asan --disable-introspection --without-curl --disable-wayland-security-context
popd
env:
CFLAGS: -O2 -Wp,-D_FORTIFY_SOURCE=2
Expand Down Expand Up @@ -236,7 +236,7 @@ jobs:
run: |
mkdir _build
pushd _build
../configure --enable-gtk-doc --enable-gtk-doc-html --enable-introspection
../configure --enable-gtk-doc --enable-gtk-doc-html --enable-introspection --disable-wayland-security-context
popd
env:
CFLAGS: -O2
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ flatpak.pc
flatpak.pp.bz2
common/flatpak-enum-types.c
common/flatpak-enum-types.h
/common/security-context-v1-protocol.c
/common/security-context-v1-protocol.h
test-libflatpak
httpcache
revokefs-fuse
Expand Down
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 @@ -68,8 +68,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 @@ -203,6 +216,7 @@ libflatpak_common_la_CFLAGS = \
$(SOUP_CFLAGS) \
$(SYSTEMD_CFLAGS) \
$(XAUTH_CFLAGS) \
$(WAYLAND_CLIENT_CFLAGS) \
$(XML_CFLAGS) \
$(NULL)
libflatpak_common_la_LIBADD = \
Expand All @@ -221,6 +235,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 @@ -8276,7 +8276,7 @@ apply_extra_data (FlatpakDir *self,
FLATPAK_RUN_FLAG_NO_A11Y_BUS_PROXY,
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
164 changes: 160 additions & 4 deletions common/flatpak-run.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,13 @@
#include <X11/Xauth.h>
#endif

#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 <glib/gi18n-lib.h>

#include <gio/gio.h>
Expand Down Expand Up @@ -406,16 +413,159 @@ flatpak_run_add_x11_args (FlatpakBwrap *bwrap,
}
}

#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_args (FlatpakBwrap *bwrap)
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;

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

unlink (socket_path);

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, "org.flatpak");
wp_security_context_v1_set_app_id (security_context, app_id);
if (instance_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 (security_context_manager)
wp_security_context_manager_v1_destroy (security_context_manager);
wl_display_disconnect (display);
return res;
}

#endif /* ENABLE_WAYLAND_SECURITY_CONTEXT */

static gboolean
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 ();
g_autofree char *wayland_socket = NULL;
g_autofree char *sandbox_wayland_socket = NULL;
gboolean res = FALSE;
gboolean security_context_available = FALSE;
struct stat statbuf;

#ifdef ENABLE_WAYLAND_SECURITY_CONTEXT
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 Expand Up @@ -1579,6 +1729,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 @@ -1802,7 +1953,7 @@ flatpak_run_add_environment_args (FlatpakBwrap *bwrap,
if (context->sockets & FLATPAK_CONTEXT_SOCKET_WAYLAND)
{
g_debug ("Allowing wayland access");
has_wayland = flatpak_run_add_wayland_args (bwrap);
has_wayland = flatpak_run_add_wayland_args (bwrap, app_id, instance_id);
}

if ((context->sockets & FLATPAK_CONTEXT_SOCKET_FALLBACK_X11) != 0)
Expand Down Expand Up @@ -2663,6 +2814,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 @@ -2901,6 +3053,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 @@ -4143,6 +4298,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 @@ -4578,7 +4734,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 @@ -4608,7 +4764,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
18 changes: 18 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,24 @@ if test "x$enable_xauth" = "xyes"; then
[Define if using xauth])
fi

AC_ARG_ENABLE([wayland-security-context],
AC_HELP_STRING([--disable-wayland-security-context],
[Disable Wayland security context use]),
[],
[enable_wayland_security_context=yes])
if test "x$enable_wayland_security_context" = "xyes"; then
PKG_CHECK_MODULES(WAYLAND_CLIENT, [wayland-client])
PKG_CHECK_MODULES(WAYLAND_SCANNER, [wayland-scanner],
[wayland_scanner=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`])
AC_SUBST(WAYLAND_SCANNER, $wayland_scanner)
PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.25],
[wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`])
AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $wayland_protocols_pkgdatadir)
AC_DEFINE([ENABLE_WAYLAND_SECURITY_CONTEXT], [1],
[Define if using Wayland security context])
fi
AM_CONDITIONAL(ENABLE_WAYLAND_SECURITY_CONTEXT, test "x$enable_wayland_security_context" = "xyes")

AC_ARG_ENABLE([gdm-env-file],
[AC_HELP_STRING([--enable-gdm-env-file], [Install gdm env.d file (not needed if systemd generators work)])],
install_gdm_env_file=$enableval, install_gdm_env_file=no)
Expand Down

0 comments on commit c2823de

Please sign in to comment.