From ba80574225488e30569d787ef7e5b0b59305adeb Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Mon, 14 May 2018 13:13:35 -0400 Subject: [PATCH] Fix a rare segfault If pip10 is installed and pyopenssl+cryptography are present in the environment pip's vendored urllib3 will automatically activate its pyopenssl adapter. This is by design so users can potentially opt-in to more up-to-date TLS versions than what are provided by their copy of Python. However, if a user has these packages & subsequently runs pip install --ignore-installed cryptography then a segfault will occur due to overwriting an mmap'd shared object. --- news/5366.bugfix | 1 + src/pip/_internal/wheel.py | 11 +++++++++++ 2 files changed, 12 insertions(+) create mode 100644 news/5366.bugfix diff --git a/news/5366.bugfix b/news/5366.bugfix new file mode 100644 index 000000000..af37e3369 --- /dev/null +++ b/news/5366.bugfix @@ -0,0 +1 @@ +Check for file existence and unlink first when clobbering existing files during a wheel install. diff --git a/src/pip/_internal/wheel.py b/src/pip/_internal/wheel.py index 8dfe2d668..045523065 100644 --- a/src/pip/_internal/wheel.py +++ b/src/pip/_internal/wheel.py @@ -285,6 +285,17 @@ def move_wheel_files(name, req, wheeldir, user=False, home=None, root=None, # uninstalled. ensure_dir(destdir) + # copyfile (called below) truncates the destination if it + # exists and then writes the new contents. This is fine in most + # cases, but can cause a segfault if pip has loaded a shared + # object (e.g. from pyopenssl through its vendored urllib3) + # Since the shared object is mmap'd an attempt to call a + # symbol in it will then cause a segfault. Unlinking the file + # allows writing of new contents while allowing the process to + # continue to use the old copy. + if os.path.exists(destfile): + os.unlink(destfile) + # We use copyfile (not move, copy, or copy2) to be extra sure # that we are not moving directories over (copyfile fails for # directories) as well as to ensure that we are not copying -- GitLab