summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2020-10-09 10:25:36 +0200
committerBastien Nocera <hadess@hadess.net>2020-10-13 13:45:43 +0200
commit34ff6b9445a464dde8d3d73d481cbfb56d767aa3 (patch)
treed34ad45ed94c30534d7eff0260fb15bd320a345d
parent46f03a237302eaefe4d6a8ef677c453db97cece3 (diff)
downloadgnome-desktop-wip/hadess/sandbox-flatpak-thumbnailer.tar.gz
thumbnail: Sandbox thumbnailers in Flatpakswip/hadess/sandbox-flatpak-thumbnailer
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.
-rw-r--r--README.md6
-rw-r--r--libgnome-desktop/gnome-desktop-thumbnail-script.c139
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;