Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-15-SP1:Update
file-roller
CVE-2020-11736.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File CVE-2020-11736.patch of Package file-roller
From 21dfcdbfe258984db89fb65243a1a888924e45a0 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] 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. Rebased by Mike Gorse <mgorse@suse.com> --- diff -urp file-roller-3.26.2.orig/src/fr-archive-libarchive.c file-roller-3.26.2/src/fr-archive-libarchive.c --- file-roller-3.26.2.orig/src/fr-archive-libarchive.c 2017-10-31 15:07:52.000000000 -0500 +++ file-roller-3.26.2/src/fr-archive-libarchive.c 2020-05-15 15:05:11.769733903 -0500 @@ -601,6 +601,149 @@ _g_output_stream_add_padding (ExtractDat } +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 (GSimpleAsyncResu 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 (GSimpleAsyncResu 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 (GSimpleAsyncResu 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 (GSimpleAsyncResu 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 (GSimpleAsyncResu 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); } Only in file-roller-3.26.2/src: fr-archive-libarchive.c.orig
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor