Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian....@packages.debian.org
Usertags: pu

Low severity issue in file-roller, I've verified with a reproducer
that the issue is fixed and did various tests to ensure that nothing
breaks functionality-wise. debdiff below.

Cheers,
        Moritz

diff -Nru file-roller-3.30.1/debian/changelog 
file-roller-3.30.1/debian/changelog
--- file-roller-3.30.1/debian/changelog 2018-12-24 02:34:26.000000000 +0100
+++ file-roller-3.30.1/debian/changelog 2020-07-08 20:12:00.000000000 +0200
@@ -1,3 +1,9 @@
+file-roller (3.30.1-2+deb10u1) buster; urgency=medium
+
+  * CVE-2020-11736 (Closes: #956638)
+
+ -- Moritz Muehlenhoff <j...@debian.org>  Wed, 08 Jul 2020 20:12:00 +0200
+
 file-roller (3.30.1-2) unstable; urgency=medium
 
   * Restore -Wl,-O1 to our LDFLAGS
diff -Nru file-roller-3.30.1/debian/patches/02_CVE-2020-11736.patch 
file-roller-3.30.1/debian/patches/02_CVE-2020-11736.patch
--- file-roller-3.30.1/debian/patches/02_CVE-2020-11736.patch   1970-01-01 
01:00:00.000000000 +0100
+++ file-roller-3.30.1/debian/patches/02_CVE-2020-11736.patch   2020-07-08 
20:12:00.000000000 +0200
@@ -0,0 +1,201 @@
+--- file-roller-3.30.1.orig/src/fr-archive-libarchive.c
++++ file-roller-3.30.1/src/fr-archive-libarchive.c
+@@ -603,6 +603,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,
+@@ -613,6 +756,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;
+@@ -623,6 +767,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 ();
+@@ -654,6 +799,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;
+               }
+@@ -862,6 +1016,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;
+ 
+@@ -896,6 +1052,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);
+ }
diff -Nru file-roller-3.30.1/debian/patches/series 
file-roller-3.30.1/debian/patches/series
--- file-roller-3.30.1/debian/patches/series    2018-12-24 02:34:26.000000000 
+0100
+++ file-roller-3.30.1/debian/patches/series    2020-07-08 20:12:00.000000000 
+0200
@@ -1 +1,3 @@
 01_package_names.patch
+
+02_CVE-2020-11736.patch

Reply via email to