Auto sync2gitlab import of file-roller-3.28.1-4.el8.src.rpm

This commit is contained in:
James Antill 2022-05-26 06:52:52 -04:00
parent e22f1ffc61
commit e17f48de37
7 changed files with 1560 additions and 1 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/file-roller-3.28.1.tar.xz

1
EMPTY
View File

@ -1 +0,0 @@

View File

@ -0,0 +1,28 @@
From 57268e51e59b61c9e3125eb0f65551c7084297e2 Mon Sep 17 00:00:00 2001
From: Paolo Bacchilega <paobac@src.gnome.org>
Date: Mon, 27 Aug 2018 15:15:42 +0200
Subject: [PATCH] Path traversal vulnerability
Do not extract files with relative paths.
[bug #794337]
---
src/glib-utils.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/glib-utils.c b/src/glib-utils.c
index 6d345243..c3901410 100644
--- a/src/glib-utils.c
+++ b/src/glib-utils.c
@@ -1079,7 +1079,7 @@ sanitize_filename (const char *file_name)
prefix_len = 0;
for (p = file_name; *p; ) {
if (ISDOT (p[0]) && ISDOT (p[1]) && (ISSLASH (p[2]) || !p[2]))
- prefix_len = p + 2 - file_name;
+ return NULL;
do {
char c = *p++;
--
2.26.2

View File

@ -0,0 +1,259 @@
From 72ac9340d9fe9554ea5c3f0ea6d08d0afa04cbf5 Mon Sep 17 00:00:00 2001
From: Paolo Bacchilega <paobac@src.gnome.org>
Date: Sun, 12 Apr 2020 11:38:35 +0200
Subject: [PATCH 1/2] libarchive: do not follow external links when extracting
files
Do not extract a file if its parent is a symbolic link to a
directory external to the destination.
---
src/fr-archive-libarchive.c | 157 ++++++++++++++++++++++++++++++++++++
1 file changed, 157 insertions(+)
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 70c07e23..8d84b2ea 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -601,6 +601,149 @@ _g_output_stream_add_padding (ExtractData *extract_data,
}
+static gboolean
+_symlink_is_external_to_destination (GFile *file,
+ const char *symlink,
+ GFile *destination,
+ GHashTable *external_links);
+
+
+static gboolean
+_g_file_is_external_link (GFile *file,
+ GFile *destination,
+ GHashTable *external_links)
+{
+ GFileInfo *info;
+ gboolean external;
+
+ if (g_hash_table_lookup (external_links, file) != NULL)
+ return TRUE;
+
+ info = g_file_query_info (file,
+ G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
+ G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
+ NULL,
+ NULL);
+
+ if (info == NULL)
+ return FALSE;
+
+ external = FALSE;
+
+ if (g_file_info_get_is_symlink (info)) {
+ if (_symlink_is_external_to_destination (file,
+ g_file_info_get_symlink_target (info),
+ destination,
+ external_links))
+ {
+ g_hash_table_insert (external_links, g_object_ref (file), GINT_TO_POINTER (1));
+ external = TRUE;
+ }
+ }
+
+ g_object_unref (info);
+
+ return external;
+}
+
+
+static gboolean
+_symlink_is_external_to_destination (GFile *file,
+ const char *symlink,
+ GFile *destination,
+ GHashTable *external_links)
+{
+ gboolean external = FALSE;
+ GFile *parent;
+ char **components;
+ int i;
+
+ if ((file == NULL) || (symlink == NULL))
+ return FALSE;
+
+ if (symlink[0] == '/')
+ return TRUE;
+
+ parent = g_file_get_parent (file);
+ components = g_strsplit (symlink, "/", -1);
+ for (i = 0; components[i] != NULL; i++) {
+ char *name = components[i];
+ GFile *tmp;
+
+ if ((name[0] == 0) || ((name[0] == '.') && (name[1] == 0)))
+ continue;
+
+ if ((name[0] == '.') && (name[1] == '.') && (name[2] == 0)) {
+ if (g_file_equal (parent, destination)) {
+ external = TRUE;
+ break;
+ }
+ else {
+ tmp = g_file_get_parent (parent);
+ g_object_unref (parent);
+ parent = tmp;
+ }
+ }
+ else {
+ tmp = g_file_get_child (parent, components[i]);
+ g_object_unref (parent);
+ parent = tmp;
+ }
+
+ if (_g_file_is_external_link (parent, destination, external_links)) {
+ external = TRUE;
+ break;
+ }
+ }
+
+ g_strfreev (components);
+ g_object_unref (parent);
+
+ return external;
+}
+
+
+static gboolean
+_g_path_is_external_to_destination (const char *relative_path,
+ GFile *destination,
+ GHashTable *external_links)
+{
+ gboolean external = FALSE;
+ GFile *parent;
+ char **components;
+ int i;
+
+ if (relative_path == NULL)
+ return FALSE;
+
+ if (destination == NULL)
+ return TRUE;
+
+ parent = g_object_ref (destination);
+ components = g_strsplit (relative_path, "/", -1);
+ for (i = 0; (components[i] != NULL) && (components[i + 1] != NULL); i++) {
+ GFile *tmp;
+
+ if (components[i][0] == 0)
+ continue;
+
+ tmp = g_file_get_child (parent, components[i]);
+ g_object_unref (parent);
+ parent = tmp;
+
+ if (_g_file_is_external_link (parent, destination, external_links)) {
+ external = TRUE;
+ break;
+ }
+ }
+
+ g_strfreev (components);
+ g_object_unref (parent);
+
+ return external;
+}
+
+
static void
extract_archive_thread (GSimpleAsyncResult *result,
GObject *object,
@@ -611,6 +754,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
GHashTable *checked_folders;
GHashTable *created_files;
GHashTable *folders_created_during_extraction;
+ GHashTable *external_links;
struct archive *a;
struct archive_entry *entry;
int r;
@@ -621,6 +765,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
checked_folders = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
created_files = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, g_object_unref);
folders_created_during_extraction = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
+ external_links = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
fr_archive_progress_set_total_files (load_data->archive, extract_data->n_files_to_extract);
a = archive_read_new ();
@@ -652,6 +797,15 @@ extract_archive_thread (GSimpleAsyncResult *result,
fullpath = (*pathname == '/') ? g_strdup (pathname) : g_strconcat ("/", pathname, NULL);
relative_path = _g_path_get_relative_basename_safe (fullpath, extract_data->base_dir, extract_data->junk_paths);
if (relative_path == NULL) {
+ fr_archive_progress_inc_completed_files (load_data->archive, 1);
+ fr_archive_progress_inc_completed_bytes (load_data->archive, archive_entry_size_is_set (entry) ? archive_entry_size (entry) : 0);
+ archive_read_data_skip (a);
+ continue;
+ }
+
+ if (_g_path_is_external_to_destination (relative_path, extract_data->destination, external_links)) {
+ fr_archive_progress_inc_completed_files (load_data->archive, 1);
+ fr_archive_progress_inc_completed_bytes (load_data->archive, archive_entry_size_is_set (entry) ? archive_entry_size (entry) : 0);
archive_read_data_skip (a);
continue;
}
@@ -860,6 +1014,8 @@ extract_archive_thread (GSimpleAsyncResult *result,
load_data->error = g_error_copy (local_error);
g_clear_error (&local_error);
}
+ else if (_symlink_is_external_to_destination (file, archive_entry_symlink (entry), extract_data->destination, external_links))
+ g_hash_table_insert (external_links, g_object_ref (file), GINT_TO_POINTER (1));
archive_read_data_skip (a);
break;
@@ -894,6 +1050,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
g_hash_table_unref (folders_created_during_extraction);
g_hash_table_unref (created_files);
g_hash_table_unref (checked_folders);
+ g_hash_table_unref (external_links);
archive_read_free (a);
extract_data_free (extract_data);
}
--
2.26.2
From 25f0759274f3be9480aaba01ed801d1308a00026 Mon Sep 17 00:00:00 2001
From: Paolo Bacchilega <paobac@src.gnome.org>
Date: Sun, 12 Apr 2020 12:19:18 +0200
Subject: [PATCH 2/2] libarchive: overwrite the symbolic link as well
---
src/fr-archive-libarchive.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 8d84b2ea..07babbc4 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -1010,11 +1010,21 @@ extract_archive_thread (GSimpleAsyncResult *result,
case AE_IFLNK:
if (! g_file_make_symbolic_link (file, archive_entry_symlink (entry), cancellable, &local_error)) {
- if (! g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_EXISTS)) {
+ g_clear_error (&local_error);
+ if (g_file_delete (file, cancellable, &local_error)) {
+ g_clear_error (&local_error);
+ if (! g_file_make_symbolic_link (file, archive_entry_symlink (entry), cancellable, &local_error))
+ load_data->error = g_error_copy (local_error);
+ }
+ else
+ load_data->error = g_error_copy (local_error);
+ }
+ else
load_data->error = g_error_copy (local_error);
g_clear_error (&local_error);
}
- else if (_symlink_is_external_to_destination (file, archive_entry_symlink (entry), extract_data->destination, external_links))
+ if ((load_data->error == NULL) && _symlink_is_external_to_destination (file, archive_entry_symlink (entry), extract_data->destination, external_links))
g_hash_table_insert (external_links, g_object_ref (file), GINT_TO_POINTER (1));
archive_read_data_skip (a);
break;
--
2.26.2

View File

@ -0,0 +1,218 @@
From 23deb42cd555b1e6b174a0bd9eaa814be5bc3558 Mon Sep 17 00:00:00 2001
From: Ondrej Holy <oholy@redhat.com>
Date: Thu, 11 Mar 2021 16:24:35 +0100
Subject: [PATCH] libarchive: Skip files with symlinks in parents
Currently, it is still possible that some files are extracted outside of
the destination dir in case of malicious archives. The checks from commit
21dfcdbf can be still bypassed in certain cases. See GNOME/file-roller#108
for more details. After some investigation, I am convinced that it would be
best to simply disallow symlinks in parents. For example, `tar` fails to
extract such files with the `ENOTDIR` error. Let's do the same here.
Fixes: https://gitlab.gnome.org/GNOME/file-roller/-/issues/108
---
src/fr-archive-libarchive.c | 136 ++++++------------------------------
1 file changed, 20 insertions(+), 116 deletions(-)
diff --git a/src/fr-archive-libarchive.c b/src/fr-archive-libarchive.c
index 07babbc4..70d3e763 100644
--- a/src/fr-archive-libarchive.c
+++ b/src/fr-archive-libarchive.c
@@ -600,115 +600,12 @@ _g_output_stream_add_padding (ExtractData *extract_data,
return success;
}
-
-static gboolean
-_symlink_is_external_to_destination (GFile *file,
- const char *symlink,
- GFile *destination,
- GHashTable *external_links);
-
-
-static gboolean
-_g_file_is_external_link (GFile *file,
- GFile *destination,
- GHashTable *external_links)
-{
- GFileInfo *info;
- gboolean external;
-
- if (g_hash_table_lookup (external_links, file) != NULL)
- return TRUE;
-
- info = g_file_query_info (file,
- G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET,
- G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
- NULL,
- NULL);
-
- if (info == NULL)
- return FALSE;
-
- external = FALSE;
-
- if (g_file_info_get_is_symlink (info)) {
- if (_symlink_is_external_to_destination (file,
- g_file_info_get_symlink_target (info),
- destination,
- external_links))
- {
- g_hash_table_insert (external_links, g_object_ref (file), GINT_TO_POINTER (1));
- external = TRUE;
- }
- }
-
- g_object_unref (info);
-
- return external;
-}
-
-
static gboolean
-_symlink_is_external_to_destination (GFile *file,
- const char *symlink,
- GFile *destination,
- GHashTable *external_links)
+_g_file_contains_symlinks_in_path (const char *relative_path,
+ GFile *destination,
+ GHashTable *symlinks)
{
- gboolean external = FALSE;
- GFile *parent;
- char **components;
- int i;
-
- if ((file == NULL) || (symlink == NULL))
- return FALSE;
-
- if (symlink[0] == '/')
- return TRUE;
-
- parent = g_file_get_parent (file);
- components = g_strsplit (symlink, "/", -1);
- for (i = 0; components[i] != NULL; i++) {
- char *name = components[i];
- GFile *tmp;
-
- if ((name[0] == 0) || ((name[0] == '.') && (name[1] == 0)))
- continue;
-
- if ((name[0] == '.') && (name[1] == '.') && (name[2] == 0)) {
- if (g_file_equal (parent, destination)) {
- external = TRUE;
- break;
- }
- else {
- tmp = g_file_get_parent (parent);
- g_object_unref (parent);
- parent = tmp;
- }
- }
- else {
- tmp = g_file_get_child (parent, components[i]);
- g_object_unref (parent);
- parent = tmp;
- }
-
- if (_g_file_is_external_link (parent, destination, external_links)) {
- external = TRUE;
- break;
- }
- }
-
- g_strfreev (components);
- g_object_unref (parent);
-
- return external;
-}
-
-
-static gboolean
-_g_path_is_external_to_destination (const char *relative_path,
- GFile *destination,
- GHashTable *external_links)
-{
- gboolean external = FALSE;
+ gboolean contains_symlinks = FALSE;
GFile *parent;
char **components;
int i;
@@ -731,8 +628,8 @@ _g_path_is_external_to_destination (const char *relative_path,
g_object_unref (parent);
parent = tmp;
- if (_g_file_is_external_link (parent, destination, external_links)) {
- external = TRUE;
+ if (g_hash_table_contains (symlinks, parent)) {
+ contains_symlinks = TRUE;
break;
}
}
@@ -740,7 +637,7 @@ _g_path_is_external_to_destination (const char *relative_path,
g_strfreev (components);
g_object_unref (parent);
- return external;
+ return contains_symlinks;
}
@@ -754,7 +651,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
GHashTable *checked_folders;
GHashTable *created_files;
GHashTable *folders_created_during_extraction;
- GHashTable *external_links;
+ GHashTable *symlinks;
struct archive *a;
struct archive_entry *entry;
int r;
@@ -765,7 +662,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
checked_folders = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
created_files = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, g_object_unref);
folders_created_during_extraction = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
- external_links = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
+ symlinks = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal, g_object_unref, NULL);
fr_archive_progress_set_total_files (load_data->archive, extract_data->n_files_to_extract);
a = archive_read_new ();
@@ -803,7 +700,14 @@ extract_archive_thread (GSimpleAsyncResult *result,
continue;
}
- if (_g_path_is_external_to_destination (relative_path, extract_data->destination, external_links)) {
+ /* Symlinks in parents are dangerous as it can easily happen
+ * that files are written outside of the destination. The tar
+ * cmd fails to extract such archives with ENOTDIR. Let's skip
+ * those files here for sure. This is most probably malicious,
+ * or corrupted archive.
+ */
+ if (_g_file_contains_symlinks_in_path (relative_path, extract_data->destination, symlinks)) {
+ g_warning ("Skipping '%s' file as it has symlink in parents.", relative_path);
fr_archive_progress_inc_completed_files (load_data->archive, 1);
fr_archive_progress_inc_completed_bytes (load_data->archive, archive_entry_size_is_set (entry) ? archive_entry_size (entry) : 0);
archive_read_data_skip (a);
@@ -1024,8 +928,8 @@ extract_archive_thread (GSimpleAsyncResult *result,
load_data->error = g_error_copy (local_error);
g_clear_error (&local_error);
}
- if ((load_data->error == NULL) && _symlink_is_external_to_destination (file, archive_entry_symlink (entry), extract_data->destination, external_links))
- g_hash_table_insert (external_links, g_object_ref (file), GINT_TO_POINTER (1));
+ if (load_data->error == NULL)
+ g_hash_table_add (symlinks, g_object_ref (file));
archive_read_data_skip (a);
break;
@@ -1060,7 +964,7 @@ extract_archive_thread (GSimpleAsyncResult *result,
g_hash_table_unref (folders_created_during_extraction);
g_hash_table_unref (created_files);
g_hash_table_unref (checked_folders);
- g_hash_table_unref (external_links);
+ g_hash_table_unref (symlinks);
archive_read_free (a);
extract_data_free (extract_data);
}
--
2.31.1

1053
file-roller.spec Normal file

File diff suppressed because it is too large Load Diff

1
sources Normal file
View File

@ -0,0 +1 @@
SHA512 (file-roller-3.28.1.tar.xz) = 5418282a91771f6b7a95ceca986c780472341ca81a6fffa169a593709121c7d4694076bf074a00e3cb7bff6df0cf9f2904cf462cca5d0fbadf6e8aafbb344a03