Skip to content

Commit

Permalink
validate-icon: Introduce validator rulesets
Browse files Browse the repository at this point in the history
Callers should pick a validator ruleset when executing the validator.
The existing rulesets are "desktop" and "notification", and have the
same parameters.
  • Loading branch information
GeorgesStavracas committed Aug 29, 2024
1 parent db9681e commit 8ac2e53
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 11 deletions.
6 changes: 5 additions & 1 deletion src/dynamic-launcher.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/notification.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
71 changes: 64 additions & 7 deletions src/validate-icon.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
};

Expand All @@ -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);

Expand All @@ -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;
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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))
{
Expand Down Expand Up @@ -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);
Expand All @@ -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");
Expand Down
23 changes: 21 additions & 2 deletions src/xdp-utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand Down
7 changes: 7 additions & 0 deletions src/xdp-utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit 8ac2e53

Please sign in to comment.