| From c7e692c61dc091d07dee573f5f424b6b427ff056 Mon Sep 17 00:00:00 2001 |
| From: Benjamin Peterson <benjamin@python.org> |
| Date: Wed, 29 Aug 2018 21:59:21 -0700 |
| Subject: [PATCH] closes bpo-34540: Convert shutil._call_external_zip to use |
| subprocess rather than distutils.spawn. (GH-8985) |
| |
| Upstream-Status: Backport |
| CVE: CVE-2018-1000802 |
| Signed-off-by: Chen Qi <Qi.Chen@windriver.com> |
| --- |
| Lib/shutil.py | 16 ++++++++++------ |
| .../Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst | 3 +++ |
| 2 files changed, 13 insertions(+), 6 deletions(-) |
| create mode 100644 Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst |
| |
| diff --git a/Lib/shutil.py b/Lib/shutil.py |
| index 3462f7c..0ab1a06 100644 |
| --- a/Lib/shutil.py |
| +++ b/Lib/shutil.py |
| @@ -413,17 +413,21 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0, |
| |
| return archive_name |
| |
| -def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False): |
| +def _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger): |
| # XXX see if we want to keep an external call here |
| if verbose: |
| zipoptions = "-r" |
| else: |
| zipoptions = "-rq" |
| - from distutils.errors import DistutilsExecError |
| - from distutils.spawn import spawn |
| + cmd = ["zip", zipoptions, zip_filename, base_dir] |
| + if logger is not None: |
| + logger.info(' '.join(cmd)) |
| + if dry_run: |
| + return |
| + import subprocess |
| try: |
| - spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run) |
| - except DistutilsExecError: |
| + subprocess.check_call(cmd) |
| + except subprocess.CalledProcessError: |
| # XXX really should distinguish between "couldn't find |
| # external 'zip' command" and "zip failed". |
| raise ExecError, \ |
| @@ -458,7 +462,7 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None): |
| zipfile = None |
| |
| if zipfile is None: |
| - _call_external_zip(base_dir, zip_filename, verbose, dry_run) |
| + _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger) |
| else: |
| if logger is not None: |
| logger.info("creating '%s' and adding '%s' to it", |
| diff --git a/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst |
| new file mode 100644 |
| index 0000000..4f68696 |
| --- /dev/null |
| +++ b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst |
| @@ -0,0 +1,3 @@ |
| +When ``shutil.make_archive`` falls back to the external ``zip`` problem, it |
| +uses :mod:`subprocess` to invoke it rather than :mod:`distutils.spawn`. This |
| +closes a possible shell injection vector. |
| -- |
| 2.7.4 |
| |