From 3b17c38b3286c6508708ca1dab73a8e57f6ecfc8 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 8 Oct 2020 13:51:01 +0200 Subject: [PATCH 1/5] thumbnail: Prepare for additional sandboxing types Use an enum instead of a boolean to track which type of sandbox mechanism to use. --- libgnome-desktop/gnome-desktop-thumbnail-script.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.c b/libgnome-desktop/gnome-desktop-thumbnail-script.c index cfbbad04..95741301 100644 --- a/libgnome-desktop/gnome-desktop-thumbnail-script.c +++ b/libgnome-desktop/gnome-desktop-thumbnail-script.c @@ -43,8 +43,13 @@ #include "gnome-desktop-thumbnail-script.h" +typedef enum { + SANDBOX_TYPE_NONE, + SANDBOX_TYPE_BWRAP +} SandboxType; + typedef struct { - gboolean sandbox; + SandboxType sandbox; char *thumbnailer_name; GArray *fd_array; /* Input/output file paths outside the sandbox */ @@ -631,7 +636,7 @@ expand_thumbnailing_cmd (const char *cmd, array = g_ptr_array_new_with_free_func (g_free); #ifdef HAVE_BWRAP - if (script->sandbox) + if (script->sandbox == SANDBOX_TYPE_BWRAP) { if (!add_bwrap (array, script)) { @@ -643,7 +648,7 @@ expand_thumbnailing_cmd (const char *cmd, #endif #ifdef ENABLE_SECCOMP - if (script->sandbox) + if (script->sandbox == SANDBOX_TYPE_BWRAP) { const char *arch; @@ -771,7 +776,7 @@ script_exec_new (const char *uri, * Flatpak as all privileges to create a new namespace are dropped when * the initial one is created. */ if (!g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR)) - exec->sandbox = TRUE; + exec->sandbox = SANDBOX_TYPE_BWRAP; #endif file = g_file_new_for_uri (uri); @@ -785,7 +790,7 @@ script_exec_new (const char *uri, } #ifdef HAVE_BWRAP - if (exec->sandbox) + if (exec->sandbox == SANDBOX_TYPE_BWRAP) { char *tmpl; const char *infile; -- GitLab From 4ed213c96601b203e41d27a5b39e50ef996ddc19 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 9 Oct 2020 10:40:56 +0200 Subject: [PATCH 2/5] thumbnail: Namespace bwrap helper function --- .../gnome-desktop-thumbnail-script.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.c b/libgnome-desktop/gnome-desktop-thumbnail-script.c index 95741301..387e5638 100644 --- a/libgnome-desktop/gnome-desktop-thumbnail-script.c +++ b/libgnome-desktop/gnome-desktop-thumbnail-script.c @@ -136,16 +136,6 @@ add_args (GPtrArray *argv_array, ...) va_end (args); } -static void -add_env (GPtrArray *array, - const char *envvar) -{ - if (g_getenv (envvar) != NULL) - add_args (array, - "--setenv", envvar, g_getenv (envvar), - NULL); -} - #ifdef ENABLE_SECCOMP static gboolean flatpak_fail (GError **error, @@ -524,6 +514,16 @@ path_is_usrmerged (const char *dir) (stat_buf_src.st_ino == stat_buf_target.st_ino); } +static void +add_bwrap_env (GPtrArray *array, + const char *envvar) +{ + if (g_getenv (envvar) != NULL) + add_args (array, + "--setenv", envvar, g_getenv (envvar), + NULL); +} + static gboolean add_bwrap (GPtrArray *array, ScriptExec *script) @@ -589,8 +589,8 @@ add_bwrap (GPtrArray *array, "--die-with-parent", NULL); - add_env (array, "G_MESSAGES_DEBUG"); - add_env (array, "G_MESSAGES_PREFIXED"); + add_bwrap_env (array, "G_MESSAGES_DEBUG"); + add_bwrap_env (array, "G_MESSAGES_PREFIXED"); /* Add gnome-desktop's install prefix if needed */ if (g_strcmp0 (INSTALL_PREFIX, "") != 0 && -- GitLab From f3fa582db6c8822b26a6b436b154df3398fad087 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 9 Oct 2020 13:33:41 +0200 Subject: [PATCH 3/5] thumbnail: Add note about getting debug output from commands --- libgnome-desktop/gnome-desktop-thumbnail-script.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.c b/libgnome-desktop/gnome-desktop-thumbnail-script.c index 387e5638..fea2ae0f 100644 --- a/libgnome-desktop/gnome-desktop-thumbnail-script.c +++ b/libgnome-desktop/gnome-desktop-thumbnail-script.c @@ -878,6 +878,8 @@ gnome_desktop_thumbnail_script_exec (const char *cmd, print_script_debug (expanded_script); + /* NOTE: Replace the error_out argument with NULL, if you want to see + * the output of the spawned command and its children */ ret = g_spawn_sync (NULL, expanded_script, NULL, G_SPAWN_SEARCH_PATH, child_setup, exec->fd_array, NULL, &error_out, &exit_status, error); -- GitLab From 46f03a237302eaefe4d6a8ef677c453db97cece3 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 9 Oct 2020 10:41:19 +0200 Subject: [PATCH 4/5] thumbnail: Let GST_DEBUG envvar through to thumbnailers To help with debugging. --- libgnome-desktop/gnome-desktop-thumbnail-script.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.c b/libgnome-desktop/gnome-desktop-thumbnail-script.c index fea2ae0f..27a19c24 100644 --- a/libgnome-desktop/gnome-desktop-thumbnail-script.c +++ b/libgnome-desktop/gnome-desktop-thumbnail-script.c @@ -591,6 +591,7 @@ add_bwrap (GPtrArray *array, add_bwrap_env (array, "G_MESSAGES_DEBUG"); add_bwrap_env (array, "G_MESSAGES_PREFIXED"); + add_bwrap_env (array, "GST_DEBUG"); /* Add gnome-desktop's install prefix if needed */ if (g_strcmp0 (INSTALL_PREFIX, "") != 0 && -- GitLab From 34ff6b9445a464dde8d3d73d481cbfb56d767aa3 Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 9 Oct 2020 10:25:36 +0200 Subject: [PATCH 5/5] thumbnail: Sandbox thumbnailers in Flatpaks Up until now, thumbnailer sandboxing was disabled in Flatpaks as bwrap cannot be used to create a namespace inside a namespace. Use Flatpak's "Spawn" method, via flatpak-spawn, to launch a separate sandbox for thumbnailing. --- README.md | 6 +- .../gnome-desktop-thumbnail-script.c | 139 +++++++++++++++++- 2 files changed, 142 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b8d26fc8..3a309b0e 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,10 @@ bwrap binary, is a non-optional dependency on platforms where it is supported and thumbnailing will silently fail when it is not installed at runtime. +[flatpak-xdg-utils](https://github.com/flatpak/flatpak-xdg-utils/)'s `flatpak-spawn` +helper is a non-optional dependency for using gnome-desktop's thumbnailer +when the app is being run within Flatpak >= 1.5.1. + How to report bugs ================== @@ -56,4 +60,4 @@ potential attack vectors. thumbnailer the only thing that can be written from inside the sandbox. - Subverting other programs to do one of those is (hopefully) prevented by only allowing it to output PNG thumbnails, because we hope PNG reader libraries are - a lot more secure than libraries to read exotic image formats. \ No newline at end of file + a lot more secure than libraries to read exotic image formats. diff --git a/libgnome-desktop/gnome-desktop-thumbnail-script.c b/libgnome-desktop/gnome-desktop-thumbnail-script.c index 27a19c24..720943a1 100644 --- a/libgnome-desktop/gnome-desktop-thumbnail-script.c +++ b/libgnome-desktop/gnome-desktop-thumbnail-script.c @@ -45,7 +45,8 @@ typedef enum { SANDBOX_TYPE_NONE, - SANDBOX_TYPE_BWRAP + SANDBOX_TYPE_BWRAP, + SANDBOX_TYPE_FLATPAK } SandboxType; typedef struct { @@ -618,6 +619,55 @@ add_bwrap (GPtrArray *array, } #endif /* HAVE_BWRAP */ +static void +add_flatpak_env (GPtrArray *array, + const char *envvar) +{ + if (g_getenv (envvar) != NULL) + { + g_autofree char *option = NULL; + + option = g_strdup_printf ("--env=%s=%s", + envvar, + g_getenv (envvar)); + add_args (array, option, NULL); + } +} + +static gboolean +add_flatpak (GPtrArray *array, + ScriptExec *script) +{ + g_autofree char *inpath = NULL; + g_autofree char *outpath = NULL; + + g_return_val_if_fail (script->outdir != NULL, FALSE); + g_return_val_if_fail (script->infile != NULL, FALSE); + + add_args (array, + "flatpak-spawn", + "--clear-env", + "--env=GIO_USE_VFS=local", + NULL); + + add_flatpak_env (array, "G_MESSAGES_DEBUG"); + add_flatpak_env (array, "G_MESSAGES_PREFIXED"); + add_flatpak_env (array, "GST_DEBUG"); + + outpath = g_strdup_printf ("--sandbox-expose-path=%s", script->outdir); + inpath = g_strdup_printf ("--sandbox-expose-path-ro=%s", script->infile); + + add_args (array, + "--watch-bus", + "--sandbox", + "--no-network", + outpath, + inpath, + NULL); + + return TRUE; +} + static char ** expand_thumbnailing_cmd (const char *cmd, ScriptExec *script, @@ -667,6 +717,16 @@ expand_thumbnailing_cmd (const char *cmd, } #endif + if (script->sandbox == SANDBOX_TYPE_FLATPAK) + { + if (!add_flatpak (array, script)) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Flatpak-spawn setup failed"); + goto bail; + } + } + got_in = got_out = FALSE; for (i = 0; cmd_elems[i] != NULL; i++) { @@ -764,6 +824,47 @@ clear_fd (gpointer data) close (*fd_p); } +static guint32 +get_portal_version (void) +{ + static guint32 version = G_MAXUINT32; + + if (version == G_MAXUINT32) + { + g_autoptr(GError) error = NULL; + g_autoptr(GDBusConnection) session_bus = + g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + g_autoptr(GVariant) reply = NULL; + + if (session_bus) + reply = g_dbus_connection_call_sync (session_bus, + "org.freedesktop.portal.Flatpak", + "/org/freedesktop/portal/Flatpak", + "org.freedesktop.DBus.Properties", + "Get", + g_variant_new ("(ss)", "org.freedesktop.portal.Flatpak", "version"), + G_VARIANT_TYPE ("(v)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + + if (reply == NULL) + { + g_debug ("Failed to get Flatpak portal version: %s", error->message); + /* Don't try again if we failed once */ + version = 0; + } + else + { + g_autoptr(GVariant) v = g_variant_get_child_value (reply, 0); + g_autoptr(GVariant) v2 = g_variant_get_variant (v); + version = g_variant_get_uint32 (v2); + } + } + + return version; +} + static ScriptExec * script_exec_new (const char *uri, GError **error) @@ -776,7 +877,14 @@ script_exec_new (const char *uri, /* Bubblewrap is not used if the application is already sandboxed in * Flatpak as all privileges to create a new namespace are dropped when * the initial one is created. */ - if (!g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR)) + if (g_file_test ("/.flatpak-info", G_FILE_TEST_IS_REGULAR)) + { + if (get_portal_version () >= 3) + exec->sandbox = SANDBOX_TYPE_FLATPAK; + else + exec->sandbox = SANDBOX_TYPE_NONE; + } + else exec->sandbox = SANDBOX_TYPE_BWRAP; #endif @@ -823,6 +931,31 @@ script_exec_new (const char *uri, } else #endif + if (exec->sandbox == SANDBOX_TYPE_FLATPAK) + { + char *tmpl; + const char *sandbox_dir; + + sandbox_dir = g_getenv ("FLATPAK_SANDBOX_DIR"); + if (!sandbox_dir || *sandbox_dir != '/') + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Incorrect sandbox directory: '%s'", sandbox_dir ? sandbox_dir : "(null)"); + goto bail; + } + + tmpl = g_build_filename (sandbox_dir, "gnome-desktop-thumbnailer-XXXXXX", NULL); + exec->outdir = g_mkdtemp (tmpl); + if (!exec->outdir) + { + g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Could not create temporary sandbox directory"); + goto bail; + } + + exec->outfile = g_build_filename (exec->outdir, "gnome-desktop-thumbnailer.png", NULL); + } + else if (exec->sandbox == SANDBOX_TYPE_NONE) { int fd; g_autofree char *tmpname = NULL; @@ -833,6 +966,8 @@ script_exec_new (const char *uri, close (fd); exec->outfile = g_steal_pointer (&tmpname); } + else + g_assert_not_reached (); return exec; -- GitLab