Blame SOURCES/312.patch

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