From aafe1d36e0225f54db8ca2ba03d8b1981c2d09e0 Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Wed, 26 Aug 2020 19:05:21 +0100 Subject: [PATCH] context: Do some syntactic normalization on filesystems Paths containing ".." are rejected: they're almost certainly a terrible idea. Paths containing "." or multiple slashes are syntactically normalized. This assumes that nobody is going to use "--filesystem=/foo/bar/" to mean "make /foo/bar available, unless it's a non-directory, in which case fail". Signed-off-by: Simon McVittie --- common/flatpak-context.c | 44 ++++++++++++++++++++++++++++++++++++++++ tests/test-exports.c | 5 +++++ 2 files changed, 49 insertions(+) diff --git a/common/flatpak-context.c b/common/flatpak-context.c index 32fb07b5..cc235d54 100644 --- a/common/flatpak-context.c +++ b/common/flatpak-context.c @@ -759,6 +759,50 @@ flatpak_context_parse_filesystem (const char *filesystem_and_mode, GError **error) { g_autofree char *filesystem = parse_filesystem_flags (filesystem_and_mode, mode_out); + char *slash; + + slash = strchr (filesystem, '/'); + + /* Forbid /../ in paths */ + if (slash != NULL) + { + if (g_str_has_prefix (slash + 1, "../") || + g_str_has_suffix (slash + 1, "/..") || + strstr (slash + 1, "/../") != NULL) + { + g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE, + _("Filesystem location \"%s\" contains \"..\""), + filesystem); + return FALSE; + } + + /* Convert "//" and "/./" to "/" */ + for (; slash != NULL; slash = strchr (slash + 1, '/')) + { + while (TRUE) + { + if (slash[1] == '/') + memmove (slash + 1, slash + 2, strlen (slash + 2) + 1); + else if (slash[1] == '.' && slash[2] == '/') + memmove (slash + 1, slash + 3, strlen (slash + 3) + 1); + else + break; + } + } + + /* Eliminate trailing "/." or "/". */ + while (TRUE) + { + slash = strrchr (filesystem, '/'); + + if (slash != NULL && + ((slash != filesystem && slash[1] == '\0') || + (slash[1] == '.' && slash[2] == '\0'))) + *slash = '\0'; + else + break; + } + } if (g_strv_contains (flatpak_context_special_filesystems, filesystem) || get_xdg_user_dir_from_string (filesystem, NULL, NULL, NULL) || diff --git a/tests/test-exports.c b/tests/test-exports.c index 21d8329e..aaccfaf4 100644 --- a/tests/test-exports.c +++ b/tests/test-exports.c @@ -272,6 +272,9 @@ typedef struct static const NotFilesystem not_filesystems[] = { { "homework", G_OPTION_ERROR_FAILED }, + { "xdg-download/foo/bar/..", G_OPTION_ERROR_BAD_VALUE }, + { "xdg-download/../foo/bar", G_OPTION_ERROR_BAD_VALUE }, + { "xdg-download/foo/../bar", G_OPTION_ERROR_BAD_VALUE }, { "xdg-run", G_OPTION_ERROR_FAILED }, }; @@ -319,6 +322,8 @@ static const Filesystem filesystems[] = { "xdg-cache/Stuff", FLATPAK_FILESYSTEM_MODE_READ_WRITE }, { "xdg-config", FLATPAK_FILESYSTEM_MODE_READ_WRITE }, { "xdg-config/Stuff", FLATPAK_FILESYSTEM_MODE_READ_WRITE }, + { "xdg-config/././///.///././.", FLATPAK_FILESYSTEM_MODE_READ_WRITE, "xdg-config" }, + { "xdg-config/////", FLATPAK_FILESYSTEM_MODE_READ_WRITE, "xdg-config" }, { "xdg-run/dbus", FLATPAK_FILESYSTEM_MODE_READ_WRITE }, };