Blame SOURCES/312.patch

17a41a
From 358b40e72a8b5ea02fec84483ec76ee727315fca Mon Sep 17 00:00:00 2001
17a41a
From: Michal Domonkos <mdomonko@redhat.com>
17a41a
Date: Thu, 3 Jan 2019 15:58:06 +0100
17a41a
Subject: [PATCH 1/2] reposync: fix-up path traversal prevention
17a41a
17a41a
Previously, pkg_download_path() would still pass if the target path was
17a41a
a "sibling" of the destination directory.
17a41a
17a41a
Example:
17a41a
17a41a
  repo_target = '/tmp/myrepo'
17a41a
  pkg_download_path = '../myrepo2/evil_file'
17a41a
  ...
17a41a
  # final path that passes the check:
17a41a
  pkg_download_path = '/tmp/myrepo2/evil_file'
17a41a
                      # ^ this is a superstring of repo_target!
17a41a
17a41a
This commit prevents that by making sure repo_target ends with a path
17a41a
separator before it is passed to startswith().  We achieve that by
17a41a
simply using join() with an empty string (see python docs).
17a41a
17a41a
In addition, normpath() is replaced by realpath() to account for
17a41a
symlinks that could also carry us outside repo_target.
17a41a
17a41a
Resolves RHEL-8 bug:
17a41a
https://bugzilla.redhat.com/show_bug.cgi?id=1600722
17a41a
---
17a41a
 plugins/reposync.py | 9 ++++++---
17a41a
 1 file changed, 6 insertions(+), 3 deletions(-)
17a41a
17a41a
diff --git a/plugins/reposync.py b/plugins/reposync.py
17a41a
index 29b911ed..0d72f559 100644
17a41a
--- a/plugins/reposync.py
17a41a
+++ b/plugins/reposync.py
17a41a
@@ -32,7 +32,7 @@
17a41a
 
17a41a
 def _pkgdir(intermediate, target):
17a41a
     cwd = dnf.i18n.ucd(os.getcwd())
17a41a
-    return os.path.normpath(os.path.join(cwd, intermediate, target))
17a41a
+    return os.path.realpath(os.path.join(cwd, intermediate, target))
17a41a
 
17a41a
 
17a41a
 class RPMPayloadLocation(dnf.repo.RPMPayload):
17a41a
@@ -118,9 +118,12 @@ def metadata_target(self, repo):
17a41a
 
17a41a
     def pkg_download_path(self, pkg):
17a41a
         repo_target = self.repo_target(pkg.repo)
17a41a
-        pkg_download_path = os.path.normpath(
17a41a
+        pkg_download_path = os.path.realpath(
17a41a
             os.path.join(repo_target, pkg.location))
17a41a
-        if not pkg_download_path.startswith(repo_target):
17a41a
+        # join() ensures repo_target ends with a path separator (otherwise the
17a41a
+        # check would pass if pkg_download_path was a "sibling" path component
17a41a
+        # of repo_target that has the same prefix).
17a41a
+        if not pkg_download_path.startswith(os.path.join(repo_target, '')):
17a41a
             raise dnf.exceptions.Error(
17a41a
                 _("Download target '{}' is outside of download path '{}'.").format(
17a41a
                     pkg_download_path, repo_target))
17a41a
17a41a
From 6e3cf05fc9a4e7559efcf37bebe5ff2998fc11b3 Mon Sep 17 00:00:00 2001
17a41a
From: Michal Domonkos <mdomonko@redhat.com>
17a41a
Date: Thu, 3 Jan 2019 16:08:37 +0100
17a41a
Subject: [PATCH 2/2] reposync: cosmetic: PEP8 whitespace fixes
17a41a
17a41a
---
17a41a
 plugins/reposync.py | 2 +-
17a41a
 1 file changed, 1 insertion(+), 1 deletion(-)
17a41a
17a41a
diff --git a/plugins/reposync.py b/plugins/reposync.py
17a41a
index 0d72f559..503e19a3 100644
17a41a
--- a/plugins/reposync.py
17a41a
+++ b/plugins/reposync.py
17a41a
@@ -46,6 +46,7 @@ def _target_params(self):
17a41a
         tp['dest'] = self.package_dir
17a41a
         return tp
17a41a
 
17a41a
+
17a41a
 @dnf.plugin.register_command
17a41a
 class RepoSyncCommand(dnf.cli.Command):
17a41a
     aliases = ('reposync',)
17a41a
@@ -190,4 +191,3 @@ def download_packages(self, repo):
17a41a
                 shutil.copy(pkg_path, target_dir)
17a41a
         if self.opts.delete:
17a41a
             self.delete_old_local_packages(pkglist)
17a41a
-