diff --git a/SOURCES/00310-use-xml-sethashsalt-in-elementtree.patch b/SOURCES/00310-use-xml-sethashsalt-in-elementtree.patch new file mode 100644 index 0000000..d336361 --- /dev/null +++ b/SOURCES/00310-use-xml-sethashsalt-in-elementtree.patch @@ -0,0 +1,54 @@ +diff --git a/Include/pyexpat.h b/Include/pyexpat.h +index 5340ef5..3fc5fa5 100644 +--- a/Include/pyexpat.h ++++ b/Include/pyexpat.h +@@ -3,7 +3,7 @@ + + /* note: you must import expat.h before importing this module! */ + +-#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.0" ++#define PyExpat_CAPI_MAGIC "pyexpat.expat_CAPI 1.1" + #define PyExpat_CAPSULE_NAME "pyexpat.expat_CAPI" + + struct PyExpat_CAPI +@@ -43,6 +43,8 @@ struct PyExpat_CAPI + XML_Parser parser, XML_UnknownEncodingHandler handler, + void *encodingHandlerData); + void (*SetUserData)(XML_Parser parser, void *userData); ++ /* might be none for expat < 2.1.0 */ ++ int (*SetHashSalt)(XML_Parser parser, unsigned long hash_salt); + /* always add new stuff to the end! */ + }; + +diff --git a/Modules/_elementtree.c b/Modules/_elementtree.c +index 379aa01..ce62081 100644 +--- a/Modules/_elementtree.c ++++ b/Modules/_elementtree.c +@@ -2500,6 +2500,11 @@ xmlparser(PyObject* self_, PyObject* args, PyObject* kw) + PyErr_NoMemory(); + return NULL; + } ++ /* expat < 2.1.0 has no XML_SetHashSalt() */ ++ if (EXPAT(SetHashSalt) != NULL) { ++ EXPAT(SetHashSalt)(self->parser, ++ (unsigned long)_Py_HashSecret.prefix); ++ } + + /* setup target handlers */ + if (!target) { +diff --git a/Modules/pyexpat.c b/Modules/pyexpat.c +index f269113..147b8a9 100644 +--- a/Modules/pyexpat.c ++++ b/Modules/pyexpat.c +@@ -2037,6 +2037,11 @@ MODULE_INITFUNC(void) + capi.SetProcessingInstructionHandler = XML_SetProcessingInstructionHandler; + capi.SetUnknownEncodingHandler = XML_SetUnknownEncodingHandler; + capi.SetUserData = XML_SetUserData; ++#if XML_COMBINED_VERSION >= 20100 ++ capi.SetHashSalt = XML_SetHashSalt; ++#else ++ capi.SetHashSalt = NULL; ++#endif + + /* export using capsule */ + capi_object = PyCapsule_New(&capi, PyExpat_CAPSULE_NAME, NULL); diff --git a/SOURCES/00314-parser-check-e_io.patch b/SOURCES/00314-parser-check-e_io.patch new file mode 100644 index 0000000..2119f58 --- /dev/null +++ b/SOURCES/00314-parser-check-e_io.patch @@ -0,0 +1,56 @@ +commit bcd39b7b9bd3a7f8a6a34410169794a6264a6fed +Author: Victor Stinner +Date: Wed Nov 7 00:45:13 2018 +0100 + + bpo-25083: Python can sometimes create incorrect .pyc files + + Python 2 never checked for I/O error when reading .py files and + thus could mistake an I/O error for EOF and create incorrect .pyc + files. This adds an check for this and aborts on an error. + + Patch by tzickel, commit f64c813de84011a84ca21d75a294861a9cc2dfdc. + + Resolves: rhbz#1629982 + +diff --git a/Include/errcode.h b/Include/errcode.h +index becec80..5c5a0f7 100644 +--- a/Include/errcode.h ++++ b/Include/errcode.h +@@ -29,6 +29,7 @@ extern "C" { + #define E_EOFS 23 /* EOF in triple-quoted string */ + #define E_EOLS 24 /* EOL in single-quoted string */ + #define E_LINECONT 25 /* Unexpected characters after a line continuation */ ++#define E_IO 26 /* I/O error */ + + #ifdef __cplusplus + } +diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c +index ee6313b..0217f2b 100644 +--- a/Parser/tokenizer.c ++++ b/Parser/tokenizer.c +@@ -1644,6 +1644,11 @@ int + PyTokenizer_Get(struct tok_state *tok, char **p_start, char **p_end) + { + int result = tok_get(tok, p_start, p_end); ++ if (tok->fp && ferror(tok->fp)) { ++ clearerr(tok->fp); ++ result = ERRORTOKEN; ++ tok->done = E_IO; ++ } + if (tok->decoding_erred) { + result = ERRORTOKEN; + tok->done = E_DECODE; +diff --git a/Python/pythonrun.c b/Python/pythonrun.c +index 0b73f3a..9f06236 100644 +--- a/Python/pythonrun.c ++++ b/Python/pythonrun.c +@@ -1643,6 +1643,9 @@ err_input(perrdetail *err) + Py_XDECREF(tb); + break; + } ++ case E_IO: ++ msg = "I/O error while reading"; ++ break; + case E_LINECONT: + msg = "unexpected character after line continuation character"; + break; diff --git a/SOURCES/00317-CVE-2019-5010-ssl-crl.patch b/SOURCES/00317-CVE-2019-5010-ssl-crl.patch new file mode 100644 index 0000000..bd53e2e --- /dev/null +++ b/SOURCES/00317-CVE-2019-5010-ssl-crl.patch @@ -0,0 +1,100 @@ +commit 88a31ffeccce13192a474f4981b9cf6cfdfe065e +Author: Victor Stinner +Date: Wed Mar 20 17:43:20 2019 +0100 + + bpo-35746: Fix segfault in ssl's cert parser (GH-11569) + + Fix a NULL pointer deref in ssl module. The cert parser did not handle CRL + distribution points with empty DP or URI correctly. A malicious or buggy + certificate can result into segfault. + + Signed-off-by: Christian Heimes + + https://bugs.python.org/issue35746 + (cherry picked from commit a37f52436f9aa4b9292878b72f3ff1480e2606c3) + + Co-authored-by: Christian Heimes + +diff --git a/Lib/test/talos-2019-0758.pem b/Lib/test/talos-2019-0758.pem +new file mode 100644 +index 0000000..13b95a7 +--- /dev/null ++++ b/Lib/test/talos-2019-0758.pem +@@ -0,0 +1,22 @@ ++-----BEGIN CERTIFICATE----- ++MIIDqDCCApKgAwIBAgIBAjALBgkqhkiG9w0BAQswHzELMAkGA1UEBhMCVUsxEDAO ++BgNVBAMTB2NvZHktY2EwHhcNMTgwNjE4MTgwMDU4WhcNMjgwNjE0MTgwMDU4WjA7 ++MQswCQYDVQQGEwJVSzEsMCoGA1UEAxMjY29kZW5vbWljb24tdm0tMi50ZXN0Lmxh ++bC5jaXNjby5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC63fGB ++J80A9Av1GB0bptslKRIUtJm8EeEu34HkDWbL6AJY0P8WfDtlXjlPaLqFa6sqH6ES ++V48prSm1ZUbDSVL8R6BYVYpOlK8/48xk4pGTgRzv69gf5SGtQLwHy8UPBKgjSZoD ++5a5k5wJXGswhKFFNqyyxqCvWmMnJWxXTt2XDCiWc4g4YAWi4O4+6SeeHVAV9rV7C ++1wxqjzKovVe2uZOHjKEzJbbIU6JBPb6TRfMdRdYOw98n1VXDcKVgdX2DuuqjCzHP ++WhU4Tw050M9NaK3eXp4Mh69VuiKoBGOLSOcS8reqHIU46Reg0hqeL8LIL6OhFHIF ++j7HR6V1X6F+BfRS/AgMBAAGjgdYwgdMwCQYDVR0TBAIwADAdBgNVHQ4EFgQUOktp ++HQjxDXXUg8prleY9jeLKeQ4wTwYDVR0jBEgwRoAUx6zgPygZ0ZErF9sPC4+5e2Io ++UU+hI6QhMB8xCzAJBgNVBAYTAlVLMRAwDgYDVQQDEwdjb2R5LWNhggkA1QEAuwb7 ++2s0wCQYDVR0SBAIwADAuBgNVHREEJzAlgiNjb2Rlbm9taWNvbi12bS0yLnRlc3Qu ++bGFsLmNpc2NvLmNvbTAOBgNVHQ8BAf8EBAMCBaAwCwYDVR0fBAQwAjAAMAsGCSqG ++SIb3DQEBCwOCAQEAvqantx2yBlM11RoFiCfi+AfSblXPdrIrHvccepV4pYc/yO6p ++t1f2dxHQb8rWH3i6cWag/EgIZx+HJQvo0rgPY1BFJsX1WnYf1/znZpkUBGbVmlJr ++t/dW1gSkNS6sPsM0Q+7HPgEv8CPDNK5eo7vU2seE0iWOkxSyVUuiCEY9ZVGaLVit ++p0C78nZ35Pdv4I+1cosmHl28+es1WI22rrnmdBpH8J1eY6WvUw2xuZHLeNVN0TzV ++Q3qq53AaCWuLOD1AjESWuUCxMZTK9DPS4JKXTK8RLyDeqOvJGjsSWp3kL0y3GaQ+ ++10T1rfkKJub2+m9A9duin1fn6tHc2wSvB7m3DA== ++-----END CERTIFICATE----- +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index f7a6746..31af578 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -68,6 +68,7 @@ WRONGCERT = data_file("XXXnonexisting.pem") + BADKEY = data_file("badkey.pem") + NOKIACERT = data_file("nokia.pem") + NULLBYTECERT = data_file("nullbytecert.pem") ++TALOS_INVALID_CRLDP = data_file("talos-2019-0758.pem") + + DHFILE = data_file("dh1024.pem") + BYTES_DHFILE = DHFILE.encode(sys.getfilesystemencoding()) +@@ -238,6 +239,27 @@ class BasicSocketTests(unittest.TestCase): + ('IP Address', '2001:DB8:0:0:0:0:0:1\n')) + ) + ++ def test_parse_cert_CVE_2019_5010(self): ++ p = ssl._ssl._test_decode_cert(TALOS_INVALID_CRLDP) ++ if support.verbose: ++ sys.stdout.write("\n" + pprint.pformat(p) + "\n") ++ self.assertEqual( ++ p, ++ { ++ 'issuer': ( ++ (('countryName', 'UK'),), (('commonName', 'cody-ca'),)), ++ 'notAfter': 'Jun 14 18:00:58 2028 GMT', ++ 'notBefore': 'Jun 18 18:00:58 2018 GMT', ++ 'serialNumber': '02', ++ 'subject': ((('countryName', 'UK'),), ++ (('commonName', ++ 'codenomicon-vm-2.test.lal.cisco.com'),)), ++ 'subjectAltName': ( ++ ('DNS', 'codenomicon-vm-2.test.lal.cisco.com'),), ++ 'version': 3 ++ } ++ ) ++ + def test_parse_all_sans(self): + p = ssl._ssl._test_decode_cert(ALLSANFILE) + self.assertEqual(p['subjectAltName'], +diff --git a/Modules/_ssl.c b/Modules/_ssl.c +index 6220bea..baea6e1 100644 +--- a/Modules/_ssl.c ++++ b/Modules/_ssl.c +@@ -1103,6 +1103,10 @@ _get_crl_dp(X509 *certificate) { + STACK_OF(GENERAL_NAME) *gns; + + dp = sk_DIST_POINT_value(dps, i); ++ if (dp->distpoint == NULL) { ++ /* Ignore empty DP value, CVE-2019-5010 */ ++ continue; ++ } + gns = dp->distpoint->name.fullname; + + for (j=0; j < sk_GENERAL_NAME_num(gns); j++) { diff --git a/SOURCES/00324-disallow-control-chars-in-http-urls.patch b/SOURCES/00324-disallow-control-chars-in-http-urls.patch new file mode 100644 index 0000000..e12aeb1 --- /dev/null +++ b/SOURCES/00324-disallow-control-chars-in-http-urls.patch @@ -0,0 +1,222 @@ +diff --git a/Lib/httplib.py b/Lib/httplib.py +index da2f346..fc8e895 100644 +--- a/Lib/httplib.py ++++ b/Lib/httplib.py +@@ -247,6 +247,15 @@ _MAXHEADERS = 100 + _is_legal_header_name = re.compile(r'\A[^:\s][^:\r\n]*\Z').match + _is_illegal_header_value = re.compile(r'\n(?![ \t])|\r(?![ \t\n])').search + ++# These characters are not allowed within HTTP URL paths. ++# See https://tools.ietf.org/html/rfc3986#section-3.3 and the ++# https://tools.ietf.org/html/rfc3986#appendix-A pchar definition. ++# Prevents CVE-2019-9740. Includes control characters such as \r\n. ++# Restrict non-ASCII characters above \x7f (0x80-0xff). ++_contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f-\xff]') ++# Arguably only these _should_ allowed: ++# _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$") ++# We are more lenient for assumed real world compatibility purposes. + + class HTTPMessage(mimetools.Message): + +@@ -926,6 +935,12 @@ class HTTPConnection: + self._method = method + if not url: + url = '/' ++ # Prevent CVE-2019-9740. ++ match = _contains_disallowed_url_pchar_re.search(url) ++ if match: ++ raise InvalidURL("URL can't contain control characters. %r " ++ "(found at least %r)" ++ % (url, match.group())) + hdr = '%s %s %s' % (method, url, self._http_vsn_str) + + self._output(hdr) +diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py +index 3845012..d2da0f8 100644 +--- a/Lib/test/test_urllib.py ++++ b/Lib/test/test_urllib.py +@@ -198,6 +198,31 @@ class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin): + finally: + self.unfakehttp() + ++ def test_url_with_control_char_rejected(self): ++ for char_no in range(0, 0x21) + range(0x7f, 0x100): ++ char = chr(char_no) ++ schemeless_url = "//localhost:7777/test%s/" % char ++ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") ++ try: ++ # urllib quotes the URL so there is no injection. ++ resp = urllib.urlopen("http:" + schemeless_url) ++ self.assertNotIn(char, resp.geturl()) ++ finally: ++ self.unfakehttp() ++ ++ def test_url_with_newline_header_injection_rejected(self): ++ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") ++ host = "localhost:7777?a=1 HTTP/1.1\r\nX-injected: header\r\nTEST: 123" ++ schemeless_url = "//" + host + ":8080/test/?test=a" ++ try: ++ # urllib quotes the URL so there is no injection. ++ resp = urllib.urlopen("http:" + schemeless_url) ++ self.assertNotIn(' ', resp.geturl()) ++ self.assertNotIn('\r', resp.geturl()) ++ self.assertNotIn('\n', resp.geturl()) ++ finally: ++ self.unfakehttp() ++ + def test_read_bogus(self): + # urlopen() should raise IOError for many error codes. + self.fakehttp('''HTTP/1.1 401 Authentication Required +@@ -786,6 +811,35 @@ class Pathname_Tests(unittest.TestCase): + class Utility_Tests(unittest.TestCase): + """Testcase to test the various utility functions in the urllib.""" + ++ def test_splithost(self): ++ splithost = urllib.splithost ++ self.assertEqual(splithost('//www.example.org:80/foo/bar/baz.html'), ++ ('www.example.org:80', '/foo/bar/baz.html')) ++ self.assertEqual(splithost('//www.example.org:80'), ++ ('www.example.org:80', '')) ++ self.assertEqual(splithost('/foo/bar/baz.html'), ++ (None, '/foo/bar/baz.html')) ++ ++ # bpo-30500: # starts a fragment. ++ self.assertEqual(splithost('//127.0.0.1#@host.com'), ++ ('127.0.0.1', '/#@host.com')) ++ self.assertEqual(splithost('//127.0.0.1#@host.com:80'), ++ ('127.0.0.1', '/#@host.com:80')) ++ self.assertEqual(splithost('//127.0.0.1:80#@host.com'), ++ ('127.0.0.1:80', '/#@host.com')) ++ ++ # Empty host is returned as empty string. ++ self.assertEqual(splithost("///file"), ++ ('', '/file')) ++ ++ # Trailing semicolon, question mark and hash symbol are kept. ++ self.assertEqual(splithost("//example.net/file;"), ++ ('example.net', '/file;')) ++ self.assertEqual(splithost("//example.net/file?"), ++ ('example.net', '/file?')) ++ self.assertEqual(splithost("//example.net/file#"), ++ ('example.net', '/file#')) ++ + def test_splitpasswd(self): + """Some of the password examples are not sensible, but it is added to + confirming to RFC2617 and addressing issue4675. +diff --git a/Lib/test/test_urllib2.py b/Lib/test/test_urllib2.py +index c317b8d..63fefd6 100644 +--- a/Lib/test/test_urllib2.py ++++ b/Lib/test/test_urllib2.py +@@ -7,12 +7,16 @@ import StringIO + + import urllib2 + from urllib2 import Request, OpenerDirector ++import httplib + + try: + import ssl + except ImportError: + ssl = None + ++from test.test_urllib import FakeHTTPMixin ++ ++ + # XXX + # Request + # CacheFTPHandler (hard to write) +@@ -1243,7 +1247,7 @@ class HandlerTests(unittest.TestCase): + self.assertEqual(len(http_handler.requests), 1) + self.assertFalse(http_handler.requests[0].has_header(auth_header)) + +-class MiscTests(unittest.TestCase): ++class MiscTests(unittest.TestCase, FakeHTTPMixin): + + def test_build_opener(self): + class MyHTTPHandler(urllib2.HTTPHandler): pass +@@ -1289,6 +1293,53 @@ class MiscTests(unittest.TestCase): + else: + self.assertTrue(False) + ++ @unittest.skipUnless(ssl, "ssl module required") ++ def test_url_with_control_char_rejected(self): ++ for char_no in range(0, 0x21) + range(0x7f, 0x100): ++ char = chr(char_no) ++ schemeless_url = "//localhost:7777/test%s/" % char ++ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") ++ try: ++ # We explicitly test urllib.request.urlopen() instead of the top ++ # level 'def urlopen()' function defined in this... (quite ugly) ++ # test suite. They use different url opening codepaths. Plain ++ # urlopen uses FancyURLOpener which goes via a codepath that ++ # calls urllib.parse.quote() on the URL which makes all of the ++ # above attempts at injection within the url _path_ safe. ++ escaped_char_repr = repr(char).replace('\\', r'\\') ++ InvalidURL = httplib.InvalidURL ++ with self.assertRaisesRegexp( ++ InvalidURL, "contain control.*" + escaped_char_repr): ++ urllib2.urlopen("http:" + schemeless_url) ++ with self.assertRaisesRegexp( ++ InvalidURL, "contain control.*" + escaped_char_repr): ++ urllib2.urlopen("https:" + schemeless_url) ++ finally: ++ self.unfakehttp() ++ ++ @unittest.skipUnless(ssl, "ssl module required") ++ def test_url_with_newline_header_injection_rejected(self): ++ self.fakehttp(b"HTTP/1.1 200 OK\r\n\r\nHello.") ++ host = "localhost:7777?a=1 HTTP/1.1\r\nX-injected: header\r\nTEST: 123" ++ schemeless_url = "//" + host + ":8080/test/?test=a" ++ try: ++ # We explicitly test urllib2.urlopen() instead of the top ++ # level 'def urlopen()' function defined in this... (quite ugly) ++ # test suite. They use different url opening codepaths. Plain ++ # urlopen uses FancyURLOpener which goes via a codepath that ++ # calls urllib.parse.quote() on the URL which makes all of the ++ # above attempts at injection within the url _path_ safe. ++ InvalidURL = httplib.InvalidURL ++ with self.assertRaisesRegexp( ++ InvalidURL, r"contain control.*\\r.*(found at least . .)"): ++ urllib2.urlopen("http:" + schemeless_url) ++ with self.assertRaisesRegexp(InvalidURL, r"contain control.*\\n"): ++ urllib2.urlopen("https:" + schemeless_url) ++ finally: ++ self.unfakehttp() ++ ++ ++ + class RequestTests(unittest.TestCase): + + def setUp(self): +diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py +index 79e862a..347b494 100644 +--- a/Lib/test/test_xmlrpc.py ++++ b/Lib/test/test_xmlrpc.py +@@ -592,7 +592,13 @@ class SimpleServerTestCase(BaseServerTestCase): + def test_partial_post(self): + # Check that a partial POST doesn't make the server loop: issue #14001. + conn = httplib.HTTPConnection(ADDR, PORT) +- conn.request('POST', '/RPC2 HTTP/1.0\r\nContent-Length: 100\r\n\r\nbye') ++ conn.send('POST /RPC2 HTTP/1.0\r\n' ++ 'Content-Length: 100\r\n\r\n' ++ 'bye HTTP/1.1\r\n' ++ 'Host: %s:%s\r\n' ++ 'Accept-Encoding: identity\r\n' ++ 'Content-Length: 0\r\n\r\n' ++ % (ADDR, PORT)) + conn.close() + + class MultiPathServerTestCase(BaseServerTestCase): +diff --git a/Lib/urllib.py b/Lib/urllib.py +index 9b31df1..2201e3e 100644 +--- a/Lib/urllib.py ++++ b/Lib/urllib.py +@@ -1079,8 +1079,7 @@ def splithost(url): + """splithost('//host[:port]/path') --> 'host[:port]', '/path'.""" + global _hostprog + if _hostprog is None: +- import re +- _hostprog = re.compile('^//([^/?]*)(.*)$') ++ _hostprog = re.compile('//([^/#?]*)(.*)', re.DOTALL) + + match = _hostprog.match(url) + if match: diff --git a/SOURCES/00325-CVE-2019-9948.patch b/SOURCES/00325-CVE-2019-9948.patch new file mode 100644 index 0000000..890bf71 --- /dev/null +++ b/SOURCES/00325-CVE-2019-9948.patch @@ -0,0 +1,37 @@ +diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py +index d2da0f8..7813b9f 100644 +--- a/Lib/test/test_urllib.py ++++ b/Lib/test/test_urllib.py +@@ -872,6 +872,17 @@ class URLopener_Tests(unittest.TestCase): + "spam://c:|windows%/:=&?~#+!$,;'@()*[]|/path/"), + "//c:|windows%/:=&?~#+!$,;'@()*[]|/path/") + ++ def test_local_file_open(self): ++ # bpo-35907, CVE-2019-9948: urllib must reject local_file:// scheme ++ class DummyURLopener(urllib.URLopener): ++ def open_local_file(self, url): ++ return url ++ for url in ('local_file://example', 'local-file://example'): ++ self.assertRaises(IOError, urllib.urlopen, url) ++ self.assertRaises(IOError, urllib.URLopener().open, url) ++ self.assertRaises(IOError, urllib.URLopener().retrieve, url) ++ self.assertRaises(IOError, DummyURLopener().open, url) ++ self.assertRaises(IOError, DummyURLopener().retrieve, url) + + # Just commented them out. + # Can't really tell why keep failing in windows and sparc. +diff --git a/Lib/urllib.py b/Lib/urllib.py +index 2201e3e..71e3637 100644 +--- a/Lib/urllib.py ++++ b/Lib/urllib.py +@@ -198,7 +198,9 @@ class URLopener: + name = 'open_' + urltype + self.type = urltype + name = name.replace('-', '_') +- if not hasattr(self, name): ++ ++ # bpo-35907: disallow the file reading with the type not allowed ++ if not hasattr(self, name) or name == 'open_local_file': + if proxy: + return self.open_unknown_proxy(proxy, fullurl, data) + else: diff --git a/SOURCES/macros.python b/SOURCES/macros.python deleted file mode 100644 index 8b168b5..0000000 --- a/SOURCES/macros.python +++ /dev/null @@ -1,73 +0,0 @@ -%py_setup setup.py -%py_shbang_opts -s - -# Use the slashes after expand so that the command starts on the same line as -# the macro -%py_build() %{expand:\\\ - CFLAGS="%{optflags}" %{__python} %{py_setup} %{?py_setup_args} build --executable="%{__python2} %{py_shbang_opts}" %{?*} - sleep 1 -} - -%py_build_egg() %{expand:\\\ - CFLAGS="%{optflags}" %{__python} %{py_setup} %{?py_setup_args} bdist_egg %{?*} - sleep 1 -} - -%py_build_wheel() %{expand:\\\ - CFLAGS="%{optflags}" %{__python} %{py_setup} %{?py_setup_args} bdist_wheel %{?*} - sleep 1 -} - -%py_install() %{expand:\\\ - CFLAGS="%{optflags}" %{__python} %{py_setup} %{?py_setup_args} install -O1 --skip-build --root %{buildroot} %{?*} -} - -%py_install_egg() %{expand:\\\ - mkdir -p %{buildroot}%{python_sitelib} - easy_install -m --prefix %{buildroot}%{_prefix} -Z dist/*-py%{python_version}.egg %{?*} -} - -%py_install_wheel() %{expand:\\\ - pip install -I dist/%{1} --root %{buildroot} --strip-file-prefix %{buildroot} --no-deps -} - -%python_provide() %{lua: - function string.starts(String,Start) - return string.sub(String,1,string.len(Start))==Start - end - package = rpm.expand("%{?1}") - vr = rpm.expand("%{?epoch:%{epoch}:}%{version}-%{release}") - if (string.starts(package, "python2-")) then - if (rpm.expand("%{?buildarch}") ~= "noarch") then - str = "Provides: python-" .. string.sub(package,9,string.len(package)) .. "%{?_isa} = " .. vr - print(rpm.expand(str)) - end - print("\\nProvides: python-") - print(string.sub(package,9,string.len(package))) - print(" = ") - print(vr) - --Obsoleting the previous default python package - print("\\nObsoletes: python-") - print(string.sub(package,9,string.len(package))) - print(" < ") - print(vr) - elseif (string.starts(package, "python" .. rpm.expand("%{python3_pkgversion}") .. "-")) then - --No unversioned provides as python3 is not default - elseif (rpm.expand("%{?python3_other_pkgversion}") ~= "" and string.starts(package, "python" .. rpm.expand("%{python3_other_pkgversion}") .. "-")) then - --No unversioned provides as python3_other is not default - elseif (string.starts(package, "pypy-")) then - --No unversioned provides as pypy is not default - elseif (string.starts(package, "pypy3-")) then - --No unversioned provides as pypy is not default - elseif (string.starts(package, "python-")) then - --Providing the current default python - print("Provides: python2-") - print(string.sub(package,8,string.len(package))) - print(" = ") - print(vr) - else - print("%python_provide: ERROR: ") - print(package) - print(" not recognized.") - end -} diff --git a/SOURCES/macros.python2 b/SOURCES/macros.python2 deleted file mode 100644 index 169d48f..0000000 --- a/SOURCES/macros.python2 +++ /dev/null @@ -1,37 +0,0 @@ -%__python2 /usr/bin/python2 -%python2_sitelib %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib())") -%python2_sitearch %(%{__python2} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1))") -%python2_version %(%{__python2} -c "import sys; sys.stdout.write('{0.major}.{0.minor}'.format(sys.version_info))") -%python2_version_nodots %(%{__python2} -c "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))") - -%py2_shbang_opts -s - -# Use the slashes after expand so that the command starts on the same line as -# the macro -%py2_build() %{expand:\\\ - CFLAGS="%{optflags}" %{__python2} %{py_setup} %{?py_setup_args} build --executable="%{__python2} %{py2_shbang_opts}" %{?*} - sleep 1 -} - -%py2_build_egg() %{expand:\\\ - CFLAGS="%{optflags}" %{__python2} %{py_setup} %{?py_setup_args} bdist_egg %{?*} - sleep 1 -} - -%py2_build_wheel() %{expand:\\\ - CFLAGS="%{optflags}" %{__python2} %{py_setup} %{?py_setup_args} bdist_wheel %{?*} - sleep 1 -} - -%py2_install() %{expand:\\\ - CFLAGS="%{optflags}" %{__python2} %{py_setup} %{?py_setup_args} install -O1 --skip-build --root %{buildroot} %{?*} -} - -%py2_install_egg() %{expand:\\\ - mkdir -p %{buildroot}%{python2_sitelib} - easy_install-%{python2_version} -m --prefix %{buildroot}%{_prefix} -Z dist/*-py%{python2_version}.egg %{?*} -} - -%py2_install_wheel() %{expand:\\\ - pip%{python2_version} install -I dist/%{1} --root %{buildroot} --strip-file-prefix %{buildroot} --no-deps -} diff --git a/SPECS/python.spec b/SPECS/python.spec index f83d23c..7538fb7 100644 --- a/SPECS/python.spec +++ b/SPECS/python.spec @@ -114,7 +114,7 @@ Summary: An interpreted, interactive, object-oriented programming language Name: %{python} # Remember to also rebase python-docs when changing this: Version: 2.7.5 -Release: 80%{?dist} +Release: 86%{?dist} License: Python Group: Development/Languages Requires: %{python}-libs%{?_isa} = %{version}-%{release} @@ -199,9 +199,6 @@ Source4: systemtap-example.stp # Written by dmalcolm; not yet sent upstream Source5: pyfuntop.stp -# Supply various useful macros for building Python 2 components: -Source6: macros.python2 - Source7: pynche # Configuration file to change ssl verification settings globally @@ -211,16 +208,6 @@ Source8: cert-verification.cfg # configuration for systemd's tmpfiles Source9: python.conf -# Supply various useful macros for building Python components: -# NOTE: The %%python_provide macro is copied directly from Fedora/EPEL, but the -# %%{python3_pkgversion} and %%{python3_other_pkgversion} macros used within it -# are missing in RHEL. However, in their absence the lua code will run fine for -# Python 2 packages and will print an error only if invoked for Python 3 -# packages (unless the python-srpm-macros package from EPEL is installed). That -# is a desirable behaviour as RHEL without EPEL does not support building -# Python 3 packages. -Source10: macros.python - # Modules/Setup.dist is ultimately used by the "makesetup" script to construct # the Makefile and config.c # @@ -1276,13 +1263,50 @@ Patch305: 00305-CVE-2016-2183.patch # Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1579432 Patch306: 00306-fix-oserror-17-upon-semaphores-creation.patch +# 00310 # +# CVE-2018-14647 +# Use XML_SetHashSalt in _elementtree +# FIXED UPSTREAM: https://bugs.python.org/issue34623 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1636838 +Patch310: 00310-use-xml-sethashsalt-in-elementtree.patch + +# 00314 # +# Python can sometimes create incorrect .pyc files: check I/O error. +# FIXED UPSTREAM: https://bugs.python.org/issue25083 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1629982 +Patch314: 00314-parser-check-e_io.patch + +# 00317 # +# CVE-2019-5010 Crash on parsing a specially crafted X509 certificate +# FIXED UPSTREAM: https://bugs.python.org/issue35746 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1666788 +Patch317: 00317-CVE-2019-5010-ssl-crl.patch + # 00320 # # Security fix for CVE-2019-9636 and CVE-2019-10160: Information Disclosure due to urlsplit improper NFKC normalization # FIXED UPSTREAM: https://bugs.python.org/issue36216 and https://bugs.python.org/issue36742 -# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689316 -# and https://bugzilla.redhat.com/show_bug.cgi?id=1718401 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689317 +# and https://bugzilla.redhat.com/show_bug.cgi?id=1718388 Patch320: 00320-CVE-2019-9636-and-CVE-2019-10160.patch +# 00324 # +# Disallow control chars in http URLs +# Security fix for CVE-2019-9740 and CVE-2019-9947 +# Fixed upstream: https://bugs.python.org/issue30458 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1704362 +# and https://bugzilla.redhat.com/show_bug.cgi?id=1703530 +# Also backport https://bugs.python.org/issue30500 as the urllib2 +# tests rely on that, and include the test_splithost case added in +# https://github.com/python/cpython/commit/f0b630b826949e51f429418e6675fb6a8a131f3c +Patch324: 00324-disallow-control-chars-in-http-urls.patch + +# 00325 # +# Unnecessary URL scheme exists to allow local_file:// reading file in urllib +# Security fix for CVE-2019-9948 +# Fixed upstream: https://bugs.python.org/issue35907 +# Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1704174 +Patch325: 00325-CVE-2019-9948.patch + # (New patches go here ^^^) # # When adding new patches to "python" and "python3" in Fedora 17 onwards, @@ -1393,6 +1417,11 @@ Summary: The libraries and header files needed for Python development Group: Development/Libraries Requires: %{python}%{?_isa} = %{version}-%{release} Requires: pkgconfig + +# Macros were previously here, but were moved to their respective packages +Requires: python-rpm-macros > 3-30 +Requires: python2-rpm-macros > 3-30 + # Needed here because of the migration of Makefile from -devel to the main # package Conflicts: %{python} < %{version}-%{release} @@ -1716,7 +1745,12 @@ mv Modules/cryptmodule.c Modules/_cryptmodule.c %patch303 -p1 %patch305 -p1 %patch306 -p1 +%patch310 -p1 +%patch314 -p1 +%patch317 -p1 %patch320 -p1 +%patch324 -p1 +%patch325 -p1 # This shouldn't be necesarry, but is right now (2.2a3) @@ -2083,11 +2117,6 @@ sed -i -e "s/'pyconfig.h'/'%{_pyconfig_h}'/" \ %{buildroot}%{pylibdir}/distutils/sysconfig.py \ %{buildroot}%{pylibdir}/sysconfig.py -# Install macros for rpm: -mkdir -p %{buildroot}/%{_sysconfdir}/rpm -install -m 644 %{SOURCE6} %{buildroot}/%{_sysconfdir}/rpm -install -m 644 %{SOURCE10} %{buildroot}/%{_sysconfdir}/rpm - # Make python folder for config files under /etc mkdir -p %{buildroot}/%{_sysconfdir}/python install -m 644 %{SOURCE8} %{buildroot}/%{_sysconfdir}/python @@ -2415,8 +2444,6 @@ rm -fr %{buildroot} %endif %{_bindir}/python%{pybasever}-config %{_libdir}/libpython%{pybasever}.so -%{_sysconfdir}/rpm/macros.python -%{_sysconfdir}/rpm/macros.python2 %files tools %defattr(-,root,root,755) @@ -2597,21 +2624,46 @@ rm -fr %{buildroot} # ====================================================== %changelog -* Tue Jun 11 2019 Charalampos Stratakis - 2.7.5-80 +* Tue Jun 11 2019 Charalampos Stratakis - 2.7.5-86 - Security fix for CVE-2019-10160 -Resolves: rhbz#1718401 +Resolves: rhbz#1718388 -* Mon May 20 2019 Charalampos Stratakis - 2.7.5-79 -- Updated fix for CVE-2019-9636 -Resolves: rhbz#1711166 +* Tue May 28 2019 Charalampos Stratakis - 2.7.5-85 +- Security fix for CVE-2019-9948 +Resolves: rhbz#1704174 -* Thu May 09 2019 Charalampos Stratakis - 2.7.5-78 +* Wed May 15 2019 Charalampos Stratakis - 2.7.5-84 +- Disallow control chars in http URLs +- Fixes CVE-2019-9740 and CVE-2019-9947 +Resolves: rhbz#1704362 and rhbz#1703530 + +* Thu May 09 2019 Charalampos Stratakis - 2.7.5-83 - Remove unversioned obsoletes -Resolves: rhbz#1708674 +Resolves: rhbz#1703600 + +* Fri May 03 2019 Charalampos Stratakis - 2.7.5-82 +- Updated fix for CVE-2019-9636 +Resolves: rhbz#1689317 -* Tue Mar 26 2019 Charalampos Stratakis - 2.7.5-77 +* Tue Mar 26 2019 Charalampos Stratakis - 2.7.5-81 - Security fix for CVE-2019-9636 -Resolves: rhbz#1689316 +Resolves: rhbz#1689317 + +* Wed Mar 20 2019 Victor Stinner - 2.7.5-80 +- Security fix for CVE-2019-5010: crash on parsing a specially crafted X509 certificate + (resolves: rhbz#1666788) + +* Wed Mar 06 2019 Tomas Orsava - 2.7.5-79 +- Moved the macros.python/2 files into their own packages python/2-rpm-macros +Resolves: rhbz#1679221 + +* Mon Feb 25 2019 Charalampos Stratakis - 2.7.5-78 +- Security fix for CVE-2018-14647 +Resolves: rhbz#1636838 + +* Tue Nov 06 2018 Victor Stinner - 2.7.5-77 +- Python can sometimes create incorrect .pyc files: check I/O error + (rhbz#1629982). * Mon Sep 10 2018 Charalampos Stratakis - 2.7.5-76 - Remove an unversioned obsoletes tag