summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <smcv@debian.org>2019-01-25 19:13:33 +0000
committerSimon McVittie <smcv@debian.org>2022-01-19 23:16:36 +0000
commit749f58ce4cb42c5a0cf4220e920666e960b3932a (patch)
treef7e169ed411e33d840e6dc8c1f973a81c5544b62
parent8bf37ae3243aa65f4015aa004c462c65e80ca703 (diff)
Replace the icon validator with the one from Flatpak 1.10.1archive/debian/1.12.1-1_bpo11+1
We avoid relying on Flatpak here, since that dependency would be quite circular. Signed-off-by: Simon McVittie <smcv@debian.org> Gbp-Pq: Name Replace-the-icon-validator-with-the-one-from-Flatpak-1.10.patch
-rw-r--r--src/Makefile.am.inc2
-rw-r--r--src/notification.c14
-rw-r--r--src/validate-icon.c212
3 files changed, 208 insertions, 20 deletions
diff --git a/src/Makefile.am.inc b/src/Makefile.am.inc
index db4ac7b..d9c202b 100644
--- a/src/Makefile.am.inc
+++ b/src/Makefile.am.inc
@@ -220,4 +220,4 @@ xdg_desktop_portal_CPPFLAGS = \
xdg_desktop_portal_validate_icon_SOURCES = src/validate-icon.c
xdg_desktop_portal_validate_icon_LDADD = $(GDK_PIXBUF_LIBS)
-xdg_desktop_portal_validate_icon_CFLAGS = $(GDK_PIXBUF_CFLAGS) -DHELPER=\"$(BWRAP)\"
+xdg_desktop_portal_validate_icon_CFLAGS = $(GDK_PIXBUF_CFLAGS) -DHELPER=\"$(BWRAP)\" -D_GNU_SOURCE=1
diff --git a/src/notification.c b/src/notification.c
index 5412609..35c779c 100644
--- a/src/notification.c
+++ b/src/notification.c
@@ -366,7 +366,7 @@ validate_icon_more (GVariant *v)
int status;
g_autofree char *err = NULL;
g_autoptr(GError) error = NULL;
- const char *icon_validator = LIBEXECDIR "/flatpak-validate-icon";
+ const char *icon_validator = LIBEXECDIR "/xdg-desktop-portal-validate-icon";
const char *args[6];
if (G_IS_THEMED_ICON (icon))
@@ -382,12 +382,6 @@ validate_icon_more (GVariant *v)
return FALSE;
}
- if (!g_file_test (icon_validator, G_FILE_TEST_EXISTS))
- {
- g_debug ("Icon validation: %s not found, accepting icon without further validation.", icon_validator);
- return TRUE;
- }
-
bytes = g_bytes_icon_get_bytes (G_BYTES_ICON (icon));
fd = g_file_open_tmp ("iconXXXXXX", &name, &error);
if (fd == -1)
@@ -420,14 +414,12 @@ validate_icon_more (GVariant *v)
if (!g_spawn_sync (NULL, (char **)args, NULL, 0, NULL, NULL, NULL, &err, &status, &error))
{
g_debug ("Icon validation: %s", error->message);
-
return FALSE;
}
- if (!g_spawn_check_exit_status (status, &error))
+ if (!g_spawn_check_exit_status (status, NULL))
{
- g_debug ("Icon validation: %s", error->message);
-
+ g_debug ("Icon validation: %s", err);
return FALSE;
}
diff --git a/src/validate-icon.c b/src/validate-icon.c
index 2bab74f..2c28527 100644
--- a/src/validate-icon.c
+++ b/src/validate-icon.c
@@ -1,9 +1,35 @@
+/*
+ * Copyright © 2018 Red Hat, Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Matthias Clasen <mclasen@redhat.com>
+ */
+
#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glib/gstdio.h>
+#include <errno.h>
+#include <unistd.h>
static int
-validate_icon (const char *filename)
+validate_icon (const char *arg_width,
+ const char *arg_height,
+ const char *filename)
{
GdkPixbufFormat *format;
+ int max_width, max_height;
int width, height;
const char *name;
const char *allowed_formats[] = { "png", "jpeg", "svg", NULL };
@@ -11,7 +37,7 @@ validate_icon (const char *filename)
g_autoptr(GError) error = NULL;
format = gdk_pixbuf_get_file_info (filename, &width, &height);
- if (format == NULL)
+ if (format == NULL)
{
g_printerr ("Format not recognized\n");
return 1;
@@ -20,13 +46,35 @@ validate_icon (const char *filename)
name = gdk_pixbuf_format_get_name (format);
if (!g_strv_contains (allowed_formats, name))
{
- g_printerr ("Format %s not allowed\n", name);
+ g_printerr ("Format %s not accepted\n", name);
return 1;
}
- if (width > 256 || height > 256)
+ if (!g_str_equal (name, "svg"))
+ {
+ max_width = g_ascii_strtoll (arg_width, NULL, 10);
+ if (max_width < 16 || max_width > 4096)
+ {
+ g_printerr ("Bad width limit: %s\n", arg_width);
+ return 1;
+ }
+
+ max_height = g_ascii_strtoll (arg_height, NULL, 10);
+ if (max_height < 16 || max_height > 4096)
+ {
+ g_printerr ("Bad height limit: %s\n", arg_height);
+ return 1;
+ }
+ }
+ else
+ {
+ /* Sanity check for vector files */
+ max_height = max_width = 4096;
+ }
+
+ if (width > max_width || height > max_height)
{
- g_printerr ("Image too large (%dx%d)\n", width, height);
+ g_printerr ("Image too large (%dx%d). Max. size %dx%d\n", width, height, max_width, max_height);
return 1;
}
@@ -40,14 +88,162 @@ validate_icon (const char *filename)
return 0;
}
+G_GNUC_NULL_TERMINATED
+static void
+add_args (GPtrArray *argv_array, ...)
+{
+ va_list args;
+ const char *arg;
+
+ va_start (args, argv_array);
+ while ((arg = va_arg (args, const gchar *)))
+ g_ptr_array_add (argv_array, g_strdup (arg));
+ va_end (args);
+}
+
+const char *
+flatpak_get_bwrap (void)
+{
+ const char *e = g_getenv ("FLATPAK_BWRAP");
+
+ if (e != NULL)
+ return e;
+ return HELPER;
+}
+
+
+static gboolean
+path_is_usrmerged (const char *dir)
+{
+ /* does /dir point to /usr/dir? */
+ g_autofree char *target = NULL;
+ GStatBuf stat_buf_src, stat_buf_target;
+
+ if (g_stat (dir, &stat_buf_src) < 0)
+ return FALSE;
+
+ target = g_strdup_printf ("/usr/%s", dir);
+
+ if (g_stat (target, &stat_buf_target) < 0)
+ return FALSE;
+
+ return (stat_buf_src.st_dev == stat_buf_target.st_dev) &&
+ (stat_buf_src.st_ino == stat_buf_target.st_ino);
+}
+
+static int
+rerun_in_sandbox (const char *arg_width,
+ const char *arg_height,
+ const char *filename)
+{
+ const char * const usrmerged_dirs[] = { "bin", "lib32", "lib64", "lib", "sbin" };
+ int i;
+ g_autoptr(GPtrArray) args = g_ptr_array_new_with_free_func (g_free);
+ char validate_icon[PATH_MAX + 1];
+ ssize_t symlink_size;
+
+ symlink_size = readlink ("/proc/self/exe", validate_icon, sizeof (validate_icon) - 1);
+ if (symlink_size < 0 || (size_t) symlink_size >= sizeof (validate_icon))
+ {
+ g_printerr ("Error: failed to read /proc/self/exe\n");
+ return 1;
+ }
+
+ validate_icon[symlink_size] = 0;
+
+ add_args (args,
+ flatpak_get_bwrap (),
+ "--unshare-ipc",
+ "--unshare-net",
+ "--unshare-pid",
+ "--ro-bind", "/usr", "/usr",
+ "--ro-bind", "/etc/ld.so.cache", "/etc/ld.so.cache",
+ "--ro-bind", validate_icon, validate_icon,
+ NULL);
+
+ /* These directories might be symlinks into /usr/... */
+ for (i = 0; i < G_N_ELEMENTS (usrmerged_dirs); i++)
+ {
+ g_autofree char *absolute_dir = g_strdup_printf ("/%s", usrmerged_dirs[i]);
+
+ if (!g_file_test (absolute_dir, G_FILE_TEST_EXISTS))
+ continue;
+
+ if (path_is_usrmerged (absolute_dir))
+ {
+ g_autofree char *symlink_target = g_strdup_printf ("/usr/%s", absolute_dir);
+
+ add_args (args,
+ "--symlink", symlink_target, absolute_dir,
+ NULL);
+ }
+ else
+ {
+ add_args (args,
+ "--ro-bind", absolute_dir, absolute_dir,
+ NULL);
+ }
+ }
+
+ add_args (args,
+ "--tmpfs", "/tmp",
+ "--proc", "/proc",
+ "--dev", "/dev",
+ "--chdir", "/",
+ "--setenv", "GIO_USE_VFS", "local",
+ "--unsetenv", "TMPDIR",
+ "--die-with-parent",
+ "--ro-bind", filename, filename,
+ NULL);
+
+ if (g_getenv ("G_MESSAGES_DEBUG"))
+ add_args (args, "--setenv", "G_MESSAGES_DEBUG", g_getenv ("G_MESSAGES_DEBUG"), NULL);
+ if (g_getenv ("G_MESSAGES_PREFIXED"))
+ add_args (args, "--setenv", "G_MESSAGES_PREFIXED", g_getenv ("G_MESSAGES_PREFIXED"), NULL);
+
+ add_args (args, validate_icon, arg_width, arg_height, filename, NULL);
+ g_ptr_array_add (args, NULL);
+
+ {
+ g_autofree char *cmdline = g_strjoinv (" ", (char **) args->pdata);
+ g_debug ("Icon validation: Spawning %s", cmdline);
+ }
+
+ execvpe (flatpak_get_bwrap (), (char **) args->pdata, NULL);
+ /* If we get here, then execvpe() failed. */
+ g_printerr ("Icon validation: execvpe %s: %s\n", flatpak_get_bwrap (), g_strerror (errno));
+ return 1;
+}
+
+static gboolean opt_sandbox;
+
+static GOptionEntry entries[] = {
+ { "sandbox", 0, 0, G_OPTION_ARG_NONE, &opt_sandbox, "Run in a sandbox", NULL },
+ { NULL }
+};
+
int
main (int argc, char *argv[])
{
- if (argc != 2)
+ GOptionContext *context;
+ GError *error = NULL;
+
+ context = g_option_context_new ("WIDTH HEIGHT PATH");
+ g_option_context_add_main_entries (context, entries, NULL);
+ if (!g_option_context_parse (context, &argc, &argv, &error))
+ {
+ g_printerr ("Error: %s\n", error->message);
+ return 1;
+ }
+
+ if (argc != 4)
{
- g_error ("Expect a single path");
+ g_printerr ("Usage: %s [OPTION…] WIDTH HEIGHT PATH\n", argv[0]);
return 1;
}
- return validate_icon (argv[1]);
+ if (opt_sandbox)
+ return rerun_in_sandbox (argv[1], argv[2], argv[3]);
+ else
+ return validate_icon (argv[1], argv[2], argv[3]);
}