diff --git a/src/dynamic-launcher.c b/src/dynamic-launcher.c index cb127637e..4ea92bfe4 100644 --- a/src/dynamic-launcher.c +++ b/src/dynamic-launcher.c @@ -161,7 +161,11 @@ validate_serialized_icon (GVariant *arg_icon_v, bytes = g_bytes_icon_get_bytes (G_BYTES_ICON (icon)); sealed_icon = xdp_sealed_fd_new_from_bytes (bytes, NULL); - return sealed_icon && xdp_validate_icon (sealed_icon, icon_format, icon_size); + return sealed_icon && + xdp_validate_icon (sealed_icon, + XDP_ICON_TYPE_DESKTOP, + icon_format, + icon_size); } static gboolean diff --git a/src/notification.c b/src/notification.c index 5eb7ffaf1..c3f204a6f 100644 --- a/src/notification.c +++ b/src/notification.c @@ -430,7 +430,7 @@ parse_serialized_icon (GVariantBuilder *builder, if (!sealed_icon) g_warning ("Failed to read icon: %s", local_error->message); - else if (xdp_validate_icon (sealed_icon, NULL, NULL)) + else if (xdp_validate_icon (sealed_icon, XDP_ICON_TYPE_NOTIFICATION, NULL, NULL)) g_variant_builder_add (builder, "{sv}", "icon", icon); } else diff --git a/src/validate-icon.c b/src/validate-icon.c index 36b3065bf..f7a2266da 100644 --- a/src/validate-icon.c +++ b/src/validate-icon.c @@ -38,19 +38,62 @@ #endif #define ICON_VALIDATOR_GROUP "Icon Validator" -#define MAX_ICON_SIZE 512 -#define MAX_SVG_ICON_SIZE 4096 -#define BUFFER_SIZE 4096 -#define MAX_FILE_SIZE (1024 * 1024 * 4) /* Max file size of 4MiB */ +typedef struct +{ + const char *name; + size_t max_icon_size; + size_t max_svg_icon_size; + size_t max_file_size; +} XdpValidatorRuleset; + +static const XdpValidatorRuleset rulesets[] = +{ + { + .name = "desktop", + .max_icon_size = 512, + .max_svg_icon_size = 4096, + .max_file_size = 1024 * 1024 * 4 /* 4MB */, + }, + { + .name = "notification", + .max_icon_size = 512, + .max_svg_icon_size = 4096, + .max_file_size = 1024 * 1024 * 4 /* 4MB */, + }, +}; + +static const XdpValidatorRuleset *ruleset = NULL; static gboolean opt_sandbox; static char *opt_path = NULL; static int opt_fd = -1; +static gboolean +option_validator_cb (const gchar *option_name, + const gchar *value, + gpointer data, + GError **error) +{ + for (size_t i = 0; i < G_N_ELEMENTS (rulesets); i++) + { + if (g_strcmp0 (value, rulesets[i].name) == 0) + { + ruleset = &rulesets[i]; + return TRUE; + } + } + + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + "Invalid ruleset '%s'. Accepted values are: desktop, notification", + value); + return FALSE; +} + static GOptionEntry entries[] = { { "sandbox", 0, 0, G_OPTION_ARG_NONE, &opt_sandbox, "Run in a sandbox", NULL }, { "path", 0, 0, G_OPTION_ARG_FILENAME, &opt_path, "Read icon data from given file path. Required to be from a trusted source.", "PATH" }, { "fd", 0, 0, G_OPTION_ARG_INT, &opt_fd, "Read icon data from given file descriptor. Required to be from a trusted source or to be sealed", "FD" }, + { "ruleset", 0, 0, G_OPTION_ARG_CALLBACK, &option_validator_cb, "The icon validator ruleset to apply. Accepted values: desktop, notification", "RULESET" }, { NULL } }; @@ -69,6 +112,8 @@ validate_icon (int input_fd) g_autofree char *name = NULL; GdkPixbuf *pixbuf; + g_assert (ruleset != NULL); + /* Ensure that we read from the beginning of the file */ lseek (input_fd, 0, SEEK_SET); @@ -87,7 +132,7 @@ validate_icon (int input_fd) return 1; } - if (g_bytes_get_size (bytes) > MAX_FILE_SIZE) + if (g_bytes_get_size (bytes) > ruleset->max_file_size) { g_printerr ("Image is bigger then the allowed size\n"); return 1; @@ -139,7 +184,7 @@ validate_icon (int input_fd) } /* Sanity check for vector files */ - max_size = g_str_equal (name, "svg") ? MAX_SVG_ICON_SIZE : MAX_ICON_SIZE; + max_size = g_str_equal (name, "svg") ? ruleset->max_svg_icon_size : ruleset->max_icon_size; /* The icon is a square so we only need to check one side */ if (width > max_size) @@ -215,6 +260,8 @@ rerun_in_sandbox (int input_fd) char validate_icon[PATH_MAX + 1]; ssize_t symlink_size; + g_assert (ruleset != NULL); + symlink_size = readlink ("/proc/self/exe", validate_icon, sizeof (validate_icon) - 1); if (symlink_size < 0 || (size_t) symlink_size >= sizeof (validate_icon)) { @@ -274,7 +321,11 @@ rerun_in_sandbox (int input_fd) add_args (args, "--setenv", "G_MESSAGES_PREFIXED", g_getenv ("G_MESSAGES_PREFIXED"), NULL); arg_input_fd = g_strdup_printf ("%d", input_fd); - add_args (args, validate_icon, "--fd", arg_input_fd, NULL); + add_args (args, + validate_icon, + "--fd", arg_input_fd, + "--ruleset", ruleset->name, + NULL); g_ptr_array_add (args, NULL); execvpe (flatpak_get_bwrap (), (char **) args->pdata, NULL); @@ -299,6 +350,12 @@ main (int argc, char *argv[]) return 1; } + if (ruleset == NULL) + { + g_printerr ("Error: A ruleset must be given with --ruleset\n"); + return 1; + } + if (opt_path != NULL && opt_fd != -1) { g_printerr ("Error: Only --path or --fd can be given\n"); diff --git a/src/xdp-utils.c b/src/xdp-utils.c index a7dcf4cd2..e70132652 100644 --- a/src/xdp-utils.c +++ b/src/xdp-utils.c @@ -552,15 +552,32 @@ xdp_has_path_prefix (const char *str, #define VALIDATOR_INPUT_FD 3 #define ICON_VALIDATOR_GROUP "Icon Validator" +static const char * +icon_type_to_string (XdpIconType icon_type) +{ + switch (icon_type) + { + case XDP_ICON_TYPE_DESKTOP: + return "desktop"; + + case XDP_ICON_TYPE_NOTIFICATION: + return "notification"; + + default: + g_assert_not_reached (); + } +} + gboolean xdp_validate_icon (XdpSealedFd *icon, + XdpIconType icon_type, char **out_format, char **out_size) { g_autofree char *format = NULL; g_autoptr(GError) error = NULL; const char *icon_validator = LIBEXECDIR "/xdg-desktop-portal-validate-icon"; - const char *args[5]; + const char *args[7]; int size; g_autofree char *output = NULL; g_autoptr(GKeyFile) key_file = NULL; @@ -578,7 +595,9 @@ xdp_validate_icon (XdpSealedFd *icon, args[1] = "--sandbox"; args[2] = "--fd"; args[3] = G_STRINGIFY (VALIDATOR_INPUT_FD); - args[4] = NULL; + args[4] = "--ruleset"; + args[5] = icon_type_to_string (icon_type); + args[6] = NULL; output = xdp_spawn_full (args, xdp_sealed_fd_dup_fd (icon), VALIDATOR_INPUT_FD, &error); if (!output) diff --git a/src/xdp-utils.h b/src/xdp-utils.h index e9d95fd69..c23eb9b3f 100644 --- a/src/xdp-utils.h +++ b/src/xdp-utils.h @@ -43,7 +43,14 @@ gboolean xdp_is_valid_app_id (const char *string); char *xdp_get_app_id_from_desktop_id (const char *desktop_id); +typedef enum +{ + XDP_ICON_TYPE_DESKTOP, + XDP_ICON_TYPE_NOTIFICATION, +} XdpIconType; + gboolean xdp_validate_icon (XdpSealedFd *icon, + XdpIconType icon_type, char **out_format, char **out_size);