blob: 125db8512a96346386848124f0bfdbecd2318903 [file] [log] [blame]
Brad Bishop6f8dcde2018-10-16 10:47:12 +08001From c7e692c61dc091d07dee573f5f424b6b427ff056 Mon Sep 17 00:00:00 2001
2From: Benjamin Peterson <benjamin@python.org>
3Date: Wed, 29 Aug 2018 21:59:21 -0700
4Subject: [PATCH] closes bpo-34540: Convert shutil._call_external_zip to use
5 subprocess rather than distutils.spawn. (GH-8985)
6
7Upstream-Status: Backport
Brad Bishop1a4b7ee2018-12-16 17:11:34 -08008CVE: CVE-2018-1000802
Brad Bishop6f8dcde2018-10-16 10:47:12 +08009Signed-off-by: Chen Qi <Qi.Chen@windriver.com>
10---
11 Lib/shutil.py | 16 ++++++++++------
12 .../Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst | 3 +++
13 2 files changed, 13 insertions(+), 6 deletions(-)
14 create mode 100644 Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
15
16diff --git a/Lib/shutil.py b/Lib/shutil.py
17index 3462f7c..0ab1a06 100644
18--- a/Lib/shutil.py
19+++ b/Lib/shutil.py
20@@ -413,17 +413,21 @@ def _make_tarball(base_name, base_dir, compress="gzip", verbose=0, dry_run=0,
21
22 return archive_name
23
24-def _call_external_zip(base_dir, zip_filename, verbose=False, dry_run=False):
25+def _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger):
26 # XXX see if we want to keep an external call here
27 if verbose:
28 zipoptions = "-r"
29 else:
30 zipoptions = "-rq"
31- from distutils.errors import DistutilsExecError
32- from distutils.spawn import spawn
33+ cmd = ["zip", zipoptions, zip_filename, base_dir]
34+ if logger is not None:
35+ logger.info(' '.join(cmd))
36+ if dry_run:
37+ return
38+ import subprocess
39 try:
40- spawn(["zip", zipoptions, zip_filename, base_dir], dry_run=dry_run)
41- except DistutilsExecError:
42+ subprocess.check_call(cmd)
43+ except subprocess.CalledProcessError:
44 # XXX really should distinguish between "couldn't find
45 # external 'zip' command" and "zip failed".
46 raise ExecError, \
47@@ -458,7 +462,7 @@ def _make_zipfile(base_name, base_dir, verbose=0, dry_run=0, logger=None):
48 zipfile = None
49
50 if zipfile is None:
51- _call_external_zip(base_dir, zip_filename, verbose, dry_run)
52+ _call_external_zip(base_dir, zip_filename, verbose, dry_run, logger)
53 else:
54 if logger is not None:
55 logger.info("creating '%s' and adding '%s' to it",
56diff --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
57new file mode 100644
58index 0000000..4f68696
59--- /dev/null
60+++ b/Misc/NEWS.d/next/Security/2018-08-28-22-11-54.bpo-34540.gfQ0TM.rst
61@@ -0,0 +1,3 @@
62+When ``shutil.make_archive`` falls back to the external ``zip`` problem, it
63+uses :mod:`subprocess` to invoke it rather than :mod:`distutils.spawn`. This
64+closes a possible shell injection vector.
65--
662.7.4
67