Blame SOURCES/312.patch

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