From 28b2615b3729ec8fe8697be6aeef7928dcb3f394 Mon Sep 17 00:00:00 2001
From: CentOS Sources <bugs@centos.org>
Date: Tue, 30 Oct 2018 04:48:22 +0000
Subject: [PATCH] import python-2.7.5-76.el7

---
 SOURCES/00298-do-not-send-IP-in-SNI-TLS-extension.patch     |   60 ++++++++
 SOURCES/00285-fix-non-deterministic-read-in-test_pty.patch  |   59 ++++++++
 SOURCES/00299-fix-ssl-module-pymax.patch                    |   24 +++
 SOURCES/00303-CVE-2018-1060-1.patch                         |   86 ++++++++++++
 SOURCES/00306-fix-oserror-17-upon-semaphores-creation.patch |   44 ++++++
 SPECS/python.spec                                           |   97 +++++++++++++
 6 files changed, 365 insertions(+), 5 deletions(-)

diff --git a/SOURCES/00285-fix-non-deterministic-read-in-test_pty.patch b/SOURCES/00285-fix-non-deterministic-read-in-test_pty.patch
new file mode 100644
index 0000000..8605809
--- /dev/null
+++ b/SOURCES/00285-fix-non-deterministic-read-in-test_pty.patch
@@ -0,0 +1,59 @@
+diff --git a/Lib/test/test_pty.py b/Lib/test/test_pty.py
+index bec38c45456..f623aa09620 100644
+--- a/Lib/test/test_pty.py
++++ b/Lib/test/test_pty.py
+@@ -11,6 +11,7 @@
+ import select
+ import signal
+ import socket
++import io # readline
+ import unittest
+ 
+ TEST_STRING_1 = "I wish to buy a fish license.\n"
+@@ -24,6 +25,16 @@ def debug(msg):
+         pass
+ 
+ 
++# Note that os.read() is nondeterministic so we need to be very careful
++# to make the test suite deterministic.  A normal call to os.read() may
++# give us less than expected.
++#
++# Beware, on my Linux system, if I put 'foo\n' into a terminal fd, I get
++# back 'foo\r\n' at the other end.  The behavior depends on the termios
++# setting.  The newline translation may be OS-specific.  To make the
++# test suite deterministic and OS-independent, the functions _readline
++# and normalize_output can be used.
++
+ def normalize_output(data):
+     # Some operating systems do conversions on newline.  We could possibly
+     # fix that by doing the appropriate termios.tcsetattr()s.  I couldn't
+@@ -45,6 +56,12 @@ def normalize_output(data):
+ 
+     return data
+ 
++def _readline(fd):
++    """Read one line.  May block forever if no newline is read."""
++    reader = io.FileIO(fd, mode='rb', closefd=False)
++    return reader.readline()
++
++
+ 
+ # Marginal testing of pty suite. Cannot do extensive 'do or fail' testing
+ # because pty code is not too portable.
+@@ -97,14 +114,14 @@ def test_basic(self):
+ 
+         debug("Writing to slave_fd")
+         os.write(slave_fd, TEST_STRING_1)
+-        s1 = os.read(master_fd, 1024)
++        s1 = _readline(master_fd)
+         self.assertEqual('I wish to buy a fish license.\n',
+                          normalize_output(s1))
+ 
+         debug("Writing chunked output")
+         os.write(slave_fd, TEST_STRING_2[:5])
+         os.write(slave_fd, TEST_STRING_2[5:])
+-        s2 = os.read(master_fd, 1024)
++        s2 = _readline(master_fd)
+         self.assertEqual('For my pet fish, Eric.\n', normalize_output(s2))
+ 
+         os.close(slave_fd)
diff --git a/SOURCES/00298-do-not-send-IP-in-SNI-TLS-extension.patch b/SOURCES/00298-do-not-send-IP-in-SNI-TLS-extension.patch
new file mode 100644
index 0000000..99ed83c
--- /dev/null
+++ b/SOURCES/00298-do-not-send-IP-in-SNI-TLS-extension.patch
@@ -0,0 +1,60 @@
+diff --git a/Modules/_ssl.c b/Modules/_ssl.c
+index d0a3830..51b192c 100644
+--- a/Modules/_ssl.c
++++ b/Modules/_ssl.c
+@@ -50,6 +50,11 @@
+ #include <sys/poll.h>
+ #endif
+ 
++#ifndef MS_WINDOWS
++/* inet_pton */
++#include <arpa/inet.h>
++#endif
++
+ /* Include OpenSSL header files */
+ #include "openssl/rsa.h"
+ #include "openssl/crypto.h"
+@@ -493,8 +498,41 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
+     SSL_set_mode(self->ssl, mode);
+ 
+ #if HAVE_SNI
+-    if (server_hostname != NULL)
+-        SSL_set_tlsext_host_name(self->ssl, server_hostname);
++    if (server_hostname != NULL) {
++/* Don't send SNI for IP addresses. We cannot simply use inet_aton() and
++ * inet_pton() here. inet_aton() may be linked weakly and inet_pton() isn't
++ * available on all platforms. Use OpenSSL's IP address parser. It's
++ * available since 1.0.2 and LibreSSL since at least 2.3.0. */
++        int send_sni = 1;
++#if OPENSSL_VERSION_NUMBER >= 0x10200000L
++        ASN1_OCTET_STRING *ip = a2i_IPADDRESS(server_hostname);
++        if (ip == NULL) {
++            send_sni = 1;
++            ERR_clear_error();
++        } else {
++            send_sni = 0;
++            ASN1_OCTET_STRING_free(ip);
++        }
++#elif defined(HAVE_INET_PTON)
++#ifdef ENABLE_IPV6
++        char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
++#else
++        char packed[sizeof(struct in_addr)];
++#endif /* ENABLE_IPV6 */
++        if (inet_pton(AF_INET, server_hostname, packed)) {
++            send_sni = 0;
++#ifdef ENABLE_IPV6
++        } else if(inet_pton(AF_INET6, server_hostname, packed)) {
++            send_sni = 0;
++#endif /* ENABLE_IPV6 */
++        } else {
++            send_sni = 1;
++        }
++#endif /* HAVE_INET_PTON */
++        if (send_sni) {
++            SSL_set_tlsext_host_name(self->ssl, server_hostname);
++        }
++    }
+ #endif
+ 
+     /* If the socket is in non-blocking mode or timeout mode, set the BIO
diff --git a/SOURCES/00299-fix-ssl-module-pymax.patch b/SOURCES/00299-fix-ssl-module-pymax.patch
new file mode 100644
index 0000000..4f8c8da
--- /dev/null
+++ b/SOURCES/00299-fix-ssl-module-pymax.patch
@@ -0,0 +1,24 @@
+From 439956a149f8a3eb44646498c63b2ef3337d5f3d Mon Sep 17 00:00:00 2001
+From: Christian Heimes <christian@python.org>
+Date: Sun, 25 Feb 2018 13:08:05 +0100
+Subject: [PATCH] Fix ssl module, Python 2.7 doesn't have Py_MAX (#5878)
+
+Signed-off-by: Christian Heimes <christian@python.org>
+---
+ Modules/_ssl.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Modules/_ssl.c b/Modules/_ssl.c
+index af66a581e15a..f9ed94dee1e1 100644
+--- a/Modules/_ssl.c
++++ b/Modules/_ssl.c
+@@ -610,7 +610,8 @@ newPySSLSocket(PySSLContext *sslctx, PySocketSockObject *sock,
+         }
+ #elif defined(HAVE_INET_PTON)
+ #ifdef ENABLE_IPV6
+-        char packed[Py_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
++	#define PySSL_MAX(x, y) (((x) > (y)) ? (x) : (y))
++        char packed[PySSL_MAX(sizeof(struct in_addr), sizeof(struct in6_addr))];
+ #else
+         char packed[sizeof(struct in_addr)];
+ #endif /* ENABLE_IPV6 */
diff --git a/SOURCES/00303-CVE-2018-1060-1.patch b/SOURCES/00303-CVE-2018-1060-1.patch
new file mode 100644
index 0000000..4d455a5
--- /dev/null
+++ b/SOURCES/00303-CVE-2018-1060-1.patch
@@ -0,0 +1,86 @@
+diff --git a/Lib/difflib.py b/Lib/difflib.py
+index 1c6fbdbedcb7..788a92df3f89 100644
+--- a/Lib/difflib.py
++++ b/Lib/difflib.py
+@@ -1103,7 +1103,7 @@ def _qformat(self, aline, bline, atags, btags):
+ 
+ import re
+ 
+-def IS_LINE_JUNK(line, pat=re.compile(r"\s*#?\s*$").match):
++def IS_LINE_JUNK(line, pat=re.compile(r"\s*(?:#\s*)?$").match):
+     r"""
+     Return 1 for ignorable line: iff `line` is blank or contains a single '#'.
+ 
+diff --git a/Lib/poplib.py b/Lib/poplib.py
+index b91e5f72d2ca..a238510b38fc 100644
+--- a/Lib/poplib.py
++++ b/Lib/poplib.py
+@@ -274,7 +274,7 @@ def rpop(self, user):
+         return self._shortcmd('RPOP %s' % user)
+ 
+ 
+-    timestamp = re.compile(r'\+OK.*(<[^>]+>)')
++    timestamp = re.compile(br'\+OK.[^<]*(<.*>)')
+ 
+     def apop(self, user, secret):
+         """Authorisation
+diff --git a/Lib/test/test_difflib.py b/Lib/test/test_difflib.py
+index 35f2c36ca70a..d8277b79b880 100644
+--- a/Lib/test/test_difflib.py
++++ b/Lib/test/test_difflib.py
+@@ -269,13 +269,33 @@ def test_range_format_context(self):
+         self.assertEqual(fmt(3,6), '4,6')
+         self.assertEqual(fmt(0,0), '0')
+ 
++class TestJunkAPIs(unittest.TestCase):
++    def test_is_line_junk_true(self):
++        for line in ['#', '  ', ' #', '# ', ' # ', '']:
++            self.assertTrue(difflib.IS_LINE_JUNK(line), repr(line))
++
++    def test_is_line_junk_false(self):
++        for line in ['##', ' ##', '## ', 'abc ', 'abc #', 'Mr. Moose is up!']:
++            self.assertFalse(difflib.IS_LINE_JUNK(line), repr(line))
++
++    def test_is_line_junk_REDOS(self):
++        evil_input = ('\t' * 1000000) + '##'
++        self.assertFalse(difflib.IS_LINE_JUNK(evil_input))
++
++    def test_is_character_junk_true(self):
++        for char in [' ', '\t']:
++            self.assertTrue(difflib.IS_CHARACTER_JUNK(char), repr(char))
++
++    def test_is_character_junk_false(self):
++        for char in ['a', '#', '\n', '\f', '\r', '\v']:
++            self.assertFalse(difflib.IS_CHARACTER_JUNK(char), repr(char))
+ 
+ def test_main():
+     difflib.HtmlDiff._default_prefix = 0
+     Doctests = doctest.DocTestSuite(difflib)
+     run_unittest(
+         TestWithAscii, TestAutojunk, TestSFpatches, TestSFbugs,
+-        TestOutputFormat, Doctests)
++        TestOutputFormat, TestJunkAPIs)
+ 
+ if __name__ == '__main__':
+     test_main()
+diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py
+index 23d688724b95..d2143759ba66 100644
+--- a/Lib/test/test_poplib.py
++++ b/Lib/test/test_poplib.py
+@@ -211,6 +211,16 @@ def test_noop(self):
+     def test_rpop(self):
+         self.assertOK(self.client.rpop('foo'))
+ 
++    def test_apop_REDOS(self):
++        # Replace welcome with very long evil welcome.
++        # NB The upper bound on welcome length is currently 2048.
++        # At this length, evil input makes each apop call take
++        # on the order of milliseconds instead of microseconds.
++        evil_welcome = b'+OK' + (b'<' * 1000000)
++        with test_support.swap_attr(self.client, 'welcome', evil_welcome):
++            # The evil welcome is invalid, so apop should throw.
++            self.assertRaises(poplib.error_proto, self.client.apop, 'a', 'kb')
++
+     def test_top(self):
+         expected =  ('+OK 116 bytes',
+                      ['From: postmaster@python.org', 'Content-Type: text/plain',
diff --git a/SOURCES/00306-fix-oserror-17-upon-semaphores-creation.patch b/SOURCES/00306-fix-oserror-17-upon-semaphores-creation.patch
new file mode 100644
index 0000000..b6070a4
--- /dev/null
+++ b/SOURCES/00306-fix-oserror-17-upon-semaphores-creation.patch
@@ -0,0 +1,44 @@
+
+# HG changeset patch
+# User Charles-François Natali <cf.natali@gmail.com>
+# Date 1455316761 0
+# Node ID d3662c088db8fb2c89f754031f18b1543419fed9
+# Parent  5715a6d9ff12053e81f7ad75268ac059b079b351
+Issue #24303: Fix random EEXIST upon multiprocessing semaphores creation with
+Linux PID namespaces enabled.
+
+diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c
+--- a/Modules/_multiprocessing/semaphore.c
++++ b/Modules/_multiprocessing/semaphore.c
+@@ -429,7 +429,7 @@ semlock_new(PyTypeObject *type, PyObject
+     int kind, maxvalue, value;
+     PyObject *result;
+     static char *kwlist[] = {"kind", "value", "maxvalue", NULL};
+-    static int counter = 0;
++    int try = 0;
+ 
+     if (!PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwlist,
+                                      &kind, &value, &maxvalue))
+@@ -440,10 +440,18 @@ semlock_new(PyTypeObject *type, PyObject
+         return NULL;
+     }
+ 
+-    PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%d", (long)getpid(), counter++);
++    /* Create a semaphore with a unique name. The bytes returned by
++     * _PyOS_URandom() are treated as unsigned long to ensure that the filename
++     * is valid (no special characters). */
++    do {
++        unsigned long suffix;
++        _PyOS_URandom((char *)&suffix, sizeof(suffix));
++        PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%lu", (long)getpid(),
++                      suffix);
++        SEM_CLEAR_ERROR();
++        handle = SEM_CREATE(buffer, value, maxvalue);
++    } while ((handle == SEM_FAILED) && (errno == EEXIST) && (++try < 100));
+ 
+-    SEM_CLEAR_ERROR();
+-    handle = SEM_CREATE(buffer, value, maxvalue);
+     /* On Windows we should fail if GetLastError()==ERROR_ALREADY_EXISTS */
+     if (handle == SEM_FAILED || SEM_GET_LAST_ERROR() != 0)
+         goto failure;
+
diff --git a/SPECS/python.spec b/SPECS/python.spec
index 2af363e..5277f37 100644
--- a/SPECS/python.spec
+++ b/SPECS/python.spec
@@ -1,3 +1,4 @@
+
 # ======================================================
 # Conditionals and other variables controlling the build
 # ======================================================
@@ -49,6 +50,13 @@
 %global with_valgrind 1
 %else
 %global with_valgrind 0
+%endif
+
+# Having more than 28 cores on a PPC machine will lead to race conditions
+# during build so we have to set a limit.
+# See: https://bugzilla.redhat.com/show_bug.cgi?id=1568974
+%ifarch ppc %{power64} &&  %_smp_ncpus_max > 28
+%global _smp_ncpus_max 28
 %endif
 
 %global with_gdbm 1
@@ -106,7 +114,7 @@
 Name: %{python}
 # Remember to also rebase python-docs when changing this:
 Version: 2.7.5
-Release: 69%{?dist}
+Release: 76%{?dist}
 License: Python
 Group: Development/Languages
 Requires: %{python}-libs%{?_isa} = %{version}-%{release}
@@ -1204,6 +1212,12 @@
 # Resolves: rhbz#1468410
 Patch282: 00282-obmalloc-mmap-threshold.patch
 
+# 00285 #
+# Fix nondeterministic read in test_pty which fails randomly in brew.
+# FIXED UPSTREAM: https://bugs.python.org/issue31158
+# Resolves: rhbz#1512160
+Patch285: 00285-fix-non-deterministic-read-in-test_pty.patch
+
 # 00287 #
 # On the creation of io.FileIO() and builtin file() objects the GIL is now released
 # when checking the file descriptor. io.FileIO.readall(), io.FileIO.read(), and
@@ -1228,11 +1242,39 @@
 # Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1546351
 Patch296: 00296-Readd-the-private-_set_hostport-api-to-httplib.patch
 
+# 00298 #
+# The SSL module no longer sends IP addresses in SNI TLS extension on
+# platforms with OpenSSL 1.0.2+ or inet_pton.
+# FIXED UPSTREAM: https://bugs.python.org/issue32185
+# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1555314
+Patch298: 00298-do-not-send-IP-in-SNI-TLS-extension.patch
+
+# 00299 #
+# Fix ssl module, Python 2.7 doesn't have Py_MAX
+# The previous patch 298 broke python2. This is a fixup.
+# FIXED UPSTREAM: https://github.com/python/cpython/pull/5878
+# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1555314
+Patch299: 00299-fix-ssl-module-pymax.patch
+
+# 00303 #
+# Fix CVE-2018-1060 and CVE-2018-1061
+# FIXED UPSTREAM: https://bugs.python.org/issue32981
+# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1563454
+# and https://bugzilla.redhat.com/show_bug.cgi?id=1549192
+Patch303: 00303-CVE-2018-1060-1.patch
+
 # 00305 #
 # Remove 3DES from the cipher list to mitigate CVE-2016-2183 (sweet32).
 # FIXED UPSTREAM: https://bugs.python.org/issue27850
-# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1584545
+# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1581901
 Patch305: 00305-CVE-2016-2183.patch
+
+# 00306 #
+# Fix OSERROR 17 due to _multiprocessing/semaphore.c
+# assuming a one-to-one Pid -> process mapping
+# FIXED UPSTREAM: https://bugs.python.org/issue24303
+# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1579432
+Patch306: 00306-fix-oserror-17-upon-semaphores-creation.patch
 
 # (New patches go here ^^^)
 #
@@ -1266,7 +1308,6 @@
 %if %{main_python}
 Obsoletes: Distutils
 Provides: Distutils
-Obsoletes: python2 
 Provides: python2 = %{version}
 Obsoletes: python-elementtree <= 1.2.6
 Obsoletes: python-sqlite < 2.3.2
@@ -1330,6 +1371,9 @@
 # prevent "import pyexpat" from failing with a linker error if someone hasn't
 # yet upgraded expat:
 Requires: expat >= 2.1.0
+
+Provides: python2-libs = %{version}-%{release}
+Provides: python2-libs%{?_isa} = %{version}-%{release}
 
 %description libs
 This package contains runtime libraries for use by Python:
@@ -1655,10 +1699,15 @@
 %patch276 -p1
 %patch281 -p1
 %patch282 -p1
+%patch285 -p1
 %patch287 -p1
 %patch295 -p1
 %patch296 -p1
+%patch298 -p1
+%patch299 -p1
+%patch303 -p1
 %patch305 -p1
+%patch306 -p1
 
 
 # This shouldn't be necesarry, but is right now (2.2a3)
@@ -2107,6 +2156,10 @@
 mkdir %{buildroot}%{_tmpfilesdir}
 cp %{SOURCE9} %{buildroot}%{_tmpfilesdir}/python.conf
 
+# Create the platform-python symlink pointing to usr/bin/python2.7
+mkdir -p %{buildroot}%{_libexecdir}
+ln -s %{_bindir}/python%{pybasever} %{buildroot}%{_libexecdir}/platform-python
+
 # ======================================================
 # Running the upstream test suite
 # ======================================================
@@ -2194,6 +2247,9 @@
 %{_bindir}/python2
 %endif
 %{_bindir}/python%{pybasever}
+
+%{_libexecdir}/platform-python
+
 %{_mandir}/*/*
 
 %files libs
@@ -2532,9 +2588,40 @@
 # ======================================================
 
 %changelog
-* Wed May 30 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-70
+* Mon Sep 10 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-76
+- Remove an unversioned obsoletes tag
+Resolves: rhbz#1627059
+
+* Mon Jul 16 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-75
+- Provide the /usr/libexec/platform-python symlink to the main binary
+Resolves: rhbz#1599159
+
+* Tue Jun 12 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-74
+- Fix OSERROR 17 due to _multiprocessing/semaphore.c assuming
+  a one-to-one Pid -> process mapping
+Resolves: rhbz#1579432
+
+* Wed May 30 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-73
 - Remove 3DS cipher to mitigate CVE-2016-2183 (sweet32).
-Resolves: rhbz#1584545
+Resolves: rhbz#1581901
+
+* Thu May 03 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-72
+- Fix CVE-2018-1060 and CVE-2018-1061
+Resolves: rhbz#1563454 and rhbz#1549192
+- Provide python2-libs from the python-libs subpackage
+Resolves: rhbz#1557460
+
+* Wed Apr 18 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-71
+- Limit the number of CPU cores when building the package on power architectures
+Resolves: rhbz#1568974
+
+* Tue Apr 17 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-70
+- Do not send IP addresses in SNI TLS extension
+Resolves: rhbz#1555314
+
+* Tue Apr 17 2018 Charalampos Stratakis <cstratak@redhat.com> - 2.7.5-69
+- Fix nondeterministic read in test_pty
+Resolves: rhbz#1512160
 
 * Mon Feb 19 2018 Tomas Orsava <torsava@redhat.com> - 2.7.5-68
 - Add Conflicts tag with old virtualenv versions due to new behaviour of

--
Gitblit v1.8.0