diff options
author | tron <tron@pkgsrc.org> | 2012-03-25 09:09:05 +0000 |
---|---|---|
committer | tron <tron@pkgsrc.org> | 2012-03-25 09:09:05 +0000 |
commit | 686492c84a92fe815426ed0b89755b99e62e38e0 (patch) | |
tree | da29752f6d9223c8eae8586f3bee888aaf127a96 /lang/python26 | |
parent | c0dd7059d324f714d310db003a9c1301d0314935 (diff) | |
download | pkgsrc-686492c84a92fe815426ed0b89755b99e62e38e0.tar.gz |
Add a fix for the DoS vulnerability reported in CVE-2012-1150 taken
from the Python Mercurial repository.
Diffstat (limited to 'lang/python26')
29 files changed, 1445 insertions, 5 deletions
diff --git a/lang/python26/Makefile b/lang/python26/Makefile index da3a735ce7e..fad7068d0c2 100644 --- a/lang/python26/Makefile +++ b/lang/python26/Makefile @@ -1,9 +1,9 @@ -# $NetBSD: Makefile,v 1.45 2012/02/15 12:21:40 drochner Exp $ +# $NetBSD: Makefile,v 1.46 2012/03/25 09:09:05 tron Exp $ .include "dist.mk" PKGNAME= python26-${PY_DISTVERSION} -PKGREVISION= 2 +PKGREVISION= 3 CATEGORIES= lang python MAINTAINER= pkgsrc-users@NetBSD.org diff --git a/lang/python26/distinfo b/lang/python26/distinfo index ea69bb1cbe6..7fe6ae27196 100644 --- a/lang/python26/distinfo +++ b/lang/python26/distinfo @@ -1,9 +1,35 @@ -$NetBSD: distinfo,v 1.43 2012/02/15 12:21:40 drochner Exp $ +$NetBSD: distinfo,v 1.44 2012/03/25 09:09:05 tron Exp $ SHA1 (Python-2.6.7.tar.bz2) = 5d35eb746e85fb3deaff8518448137c9b9fb6daa RMD160 (Python-2.6.7.tar.bz2) = 513e84a7cb76ca876e3803bb03ed558bd0378063 Size (Python-2.6.7.tar.bz2) = 11084667 bytes SHA1 (patch-CVE-2012-0845) = 1c0a8d7224b6b5cb65b24d38ac0967f8f8fb2da9 +SHA1 (patch-CVE-2012-1150-Doc_library_sys.rst) = c3f3904d982c0d859c08edaf33925abcc99ebdcf +SHA1 (patch-CVE-2012-1150-Doc_reference_datamodel.rst) = e53c527787595987452d9237174af4bc2f1a68e4 +SHA1 (patch-CVE-2012-1150-Doc_using_cmdline.rst) = cbb8cb9f664d22f551a967f299fac64ca8eac7bd +SHA1 (patch-CVE-2012-1150-Include_object.h) = e57beb2eea5af04ddbb6e824317835b73173f4ec +SHA1 (patch-CVE-2012-1150-Include_pydebug.h) = 4e13444b917d5a259e61e3959d355a430cf61e03 +SHA1 (patch-CVE-2012-1150-Include_pythonrun.h) = c3f6793e6960f442ec6d6cc8dbffe6effbd13a0c +SHA1 (patch-CVE-2012-1150-Lib_os.py) = 7c9788f276461856451fb48de59eb1e1f1a6b438 +SHA1 (patch-CVE-2012-1150-Lib_test_test_cmd_line.py) = 13608aed790f1aaf269ada63460999744d09b910 +SHA1 (patch-CVE-2012-1150-Lib_test_test_hash.py) = 6ae538e20d6947d8be200b912af27afe908e7fdd +SHA1 (patch-CVE-2012-1150-Lib_test_test_os.py) = cf68b426d48a3b77ab5c4ab0cd5fedad77d9dd32 +SHA1 (patch-CVE-2012-1150-Lib_test_test_set.py) = 6b8a8dbbe1fcd5715b23c5ab740b28ec1c44a856 +SHA1 (patch-CVE-2012-1150-Lib_test_test_support.py) = ac8242d1071bf2b291279487ee7ccbeddbd3613f +SHA1 (patch-CVE-2012-1150-Lib_test_test_symtable.py) = 8d43b31d3366544807ff20a2d98103165928ea5d +SHA1 (patch-CVE-2012-1150-Lib_test_test_sys.py) = a3886d3a280aa418d82e8e3795ed488820437c28 +SHA1 (patch-CVE-2012-1150-Misc_NEWS) = 92974696178b465195945c791de955fbe3125f7a +SHA1 (patch-CVE-2012-1150-Misc_python.man) = a4e618043c08c789264adaa3ee5f09c2dfbe1508 +SHA1 (patch-CVE-2012-1150-Modules_main.c) = 8916657b45bdfe5d116260e3de0645f748e9b64c +SHA1 (patch-CVE-2012-1150-Modules_posixmodule.c) = 059058a313a597cc747cfe389eb646e81d87b13b +SHA1 (patch-CVE-2012-1150-Objects_bufferobject.c) = e5e929b63ad534073d49ca12906aa7e7a8261c8b +SHA1 (patch-CVE-2012-1150-Objects_object.c) = 653103325c5aed7b27da2a4461b5065c92298218 +SHA1 (patch-CVE-2012-1150-Objects_stringobject.c) = b8d37c6c19cbd800893a8882033e390ad209a357 +SHA1 (patch-CVE-2012-1150-Objects_unicodeobject.c) = bd404f45211bcc20f052acddb6ae97180ac976dc +SHA1 (patch-CVE-2012-1150-PCbuild_pythoncore.vcproj) = 528a0ec62f5628fe9d66fba0463cb03b9824b992 +SHA1 (patch-CVE-2012-1150-Python_pythonrun.c) = 2ff4cbe5df8b3e2cab1e295436ed89be77f14071 +SHA1 (patch-CVE-2012-1150-Python_random.c) = 43773aa0dfddf6d7727e09b319145f3c42ada9b7 +SHA1 (patch-CVE-2012-1150-Python_sysmodule.c) = 08364378c767b014295d3ac17a4853fd3bf07ac7 SHA1 (patch-Mac_Modules_fm___Fmmodule.c) = b9314bccb51b4fe672b81559068f7a79d2965f94 SHA1 (patch-Mac_Modules_qd___Qdmodule.c) = 45c748b15b9436d45ba137460389638aa7108c8d SHA1 (patch-Mac_Modules_qdoffs___Qdoffsmodule.c) = 9994f0c1a908f18f1f3df3f05b184f082c018365 @@ -19,7 +45,7 @@ SHA1 (patch-am) = 380dfaa8ca90532a52dcca972e34965f6e64fce1 SHA1 (patch-an) = 17b4e17b3b562c29a050e9bb20447084ce82b8ab SHA1 (patch-ao) = 8c6a156b0f0c2a6d319658477fff348e6a0c3603 SHA1 (patch-ap) = d23a869a449ab9dc166cfa149913b20c9acad9cb -SHA1 (patch-au) = 38030fc45afc2a8f53a41f26b649e731642b9148 +SHA1 (patch-au) = 2da987e72bf239dbef6e1301b891fc57b66e6d86 SHA1 (patch-av) = d6bf0419015656a8d2f13d3132873e453c8a6b6e SHA1 (patch-az) = 473419352f6e1ff3c6e6268e81457e6f8a1fccb8 SHA1 (patch-ba) = 97dcf72d7380a2d257220669845c52a698165fcf diff --git a/lang/python26/patches/patch-CVE-2012-1150-Doc_library_sys.rst b/lang/python26/patches/patch-CVE-2012-1150-Doc_library_sys.rst new file mode 100644 index 00000000000..66ba0ab659e --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Doc_library_sys.rst @@ -0,0 +1,20 @@ +$NetBSD: patch-CVE-2012-1150-Doc_library_sys.rst,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Doc/library/sys.rst.orig 2010-08-01 23:10:15.000000000 +0100 ++++ Doc/library/sys.rst 2012-03-25 09:51:50.000000000 +0100 +@@ -289,6 +289,11 @@ + +------------------------------+------------------------------------------+ + | :const:`bytes_warning` | -b | + +------------------------------+------------------------------------------+ ++ +------------------------------+------------------------------------------+ ++ | :const:`hash_randomization` | -R | ++ | | | ++ | | .. versionadded:: 2.6.8 | ++ +------------------------------+------------------------------------------+ + + .. versionadded:: 2.6 + diff --git a/lang/python26/patches/patch-CVE-2012-1150-Doc_reference_datamodel.rst b/lang/python26/patches/patch-CVE-2012-1150-Doc_reference_datamodel.rst new file mode 100644 index 00000000000..7b693e93ad2 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Doc_reference_datamodel.rst @@ -0,0 +1,17 @@ +$NetBSD: patch-CVE-2012-1150-Doc_reference_datamodel.rst,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Doc/reference/datamodel.rst.orig 2010-05-19 15:04:44.000000000 +0100 ++++ Doc/reference/datamodel.rst 2012-03-25 09:51:50.000000000 +0100 +@@ -1273,6 +1273,8 @@ + modules are still available at the time when the :meth:`__del__` method is + called. + ++ See also the :option:`-R` command-line option. ++ + + .. method:: object.__repr__(self) + diff --git a/lang/python26/patches/patch-CVE-2012-1150-Doc_using_cmdline.rst b/lang/python26/patches/patch-CVE-2012-1150-Doc_using_cmdline.rst new file mode 100644 index 00000000000..85c8fb2e2d5 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Doc_using_cmdline.rst @@ -0,0 +1,75 @@ +$NetBSD: patch-CVE-2012-1150-Doc_using_cmdline.rst,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Doc/using/cmdline.rst.orig 2010-07-09 08:51:43.000000000 +0100 ++++ Doc/using/cmdline.rst 2012-03-25 09:51:50.000000000 +0100 +@@ -21,7 +21,7 @@ + + When invoking Python, you may specify any of these options:: + +- python [-BdEiOQsStuUvVWxX3?] [-c command | -m module-name | script | - ] [args] ++ python [-BdEiOQsRStuUvVWxX3?] [-c command | -m module-name | script | - ] [args] + + The most common use case is, of course, a simple invocation of a script:: + +@@ -239,6 +239,29 @@ + :pep:`238` -- Changing the division operator + + ++.. cmdoption:: -R ++ ++ Turn on hash randomization, so that the :meth:`__hash__` values of str, ++ bytes and datetime objects are "salted" with an unpredictable random value. ++ Although they remain constant within an individual Python process, they are ++ not predictable between repeated invocations of Python. ++ ++ This is intended to provide protection against a denial-of-service caused by ++ carefully-chosen inputs that exploit the worst case performance of a dict ++ insertion, O(n^2) complexity. See ++ http://www.ocert.org/advisories/ocert-2011-003.html for details. ++ ++ Changing hash values affects the order in which keys are retrieved from a ++ dict. Although Python has never made guarantees about this ordering (and it ++ typically varies between 32-bit and 64-bit builds), enough real-world code ++ implicitly relies on this non-guaranteed behavior that the randomization is ++ disabled by default. ++ ++ See also :envvar:`PYTHONHASHSEED`. ++ ++ .. versionadded:: 2.6.8 ++ ++ + .. cmdoption:: -s + + Don't add user site directory to sys.path +@@ -501,6 +524,27 @@ + + .. versionadded:: 2.6 + ++.. envvar:: PYTHONHASHSEED ++ ++ If this variable is set to ``random``, the effect is the same as specifying ++ the :option:`-R` option: a random value is used to seed the hashes of str, ++ bytes and datetime objects. ++ ++ If :envvar:`PYTHONHASHSEED` is set to an integer value, it is used as a ++ fixed seed for generating the hash() of the types covered by the hash ++ randomization. ++ ++ Its purpose is to allow repeatable hashing, such as for selftests for the ++ interpreter itself, or to allow a cluster of python processes to share hash ++ values. ++ ++ The integer must be a decimal number in the range [0,4294967295]. ++ Specifying the value 0 will lead to the same hash values as when hash ++ randomization is disabled. ++ ++ .. versionadded:: 2.6.8 ++ ++ + .. envvar:: PYTHONIOENCODING + + Overrides the encoding used for stdin/stdout/stderr, in the syntax diff --git a/lang/python26/patches/patch-CVE-2012-1150-Include_object.h b/lang/python26/patches/patch-CVE-2012-1150-Include_object.h new file mode 100644 index 00000000000..392b4073216 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Include_object.h @@ -0,0 +1,21 @@ +$NetBSD: patch-CVE-2012-1150-Include_object.h,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Include/object.h.orig 2010-05-09 16:15:40.000000000 +0100 ++++ Include/object.h 2012-03-25 09:51:50.000000000 +0100 +@@ -506,6 +506,12 @@ + PyAPI_FUNC(long) _Py_HashDouble(double); + PyAPI_FUNC(long) _Py_HashPointer(void*); + ++typedef struct { ++ long prefix; ++ long suffix; ++} _Py_HashSecret_t; ++PyAPI_DATA(_Py_HashSecret_t) _Py_HashSecret; ++ + /* Helper for passing objects to printf and the like */ + #define PyObject_REPR(obj) PyString_AS_STRING(PyObject_Repr(obj)) + diff --git a/lang/python26/patches/patch-CVE-2012-1150-Include_pydebug.h b/lang/python26/patches/patch-CVE-2012-1150-Include_pydebug.h new file mode 100644 index 00000000000..88320925cda --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Include_pydebug.h @@ -0,0 +1,16 @@ +$NetBSD: patch-CVE-2012-1150-Include_pydebug.h,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Include/pydebug.h.orig 2008-05-06 23:41:46.000000000 +0100 ++++ Include/pydebug.h 2012-03-25 09:51:50.000000000 +0100 +@@ -26,6 +26,7 @@ + PyAPI_DATA(int) _Py_QnewFlag; + /* Warn about 3.x issues */ + PyAPI_DATA(int) Py_Py3kWarningFlag; ++PyAPI_DATA(int) Py_HashRandomizationFlag; + + /* this is a wrapper around getenv() that pays attention to + Py_IgnoreEnvironmentFlag. It should be used for getting variables like diff --git a/lang/python26/patches/patch-CVE-2012-1150-Include_pythonrun.h b/lang/python26/patches/patch-CVE-2012-1150-Include_pythonrun.h new file mode 100644 index 00000000000..8ad112caf2a --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Include_pythonrun.h @@ -0,0 +1,17 @@ +$NetBSD: patch-CVE-2012-1150-Include_pythonrun.h,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Include/pythonrun.h.orig 2010-05-09 16:15:40.000000000 +0100 ++++ Include/pythonrun.h 2012-03-25 09:51:50.000000000 +0100 +@@ -168,6 +168,8 @@ + PyAPI_FUNC(PyOS_sighandler_t) PyOS_getsig(int); + PyAPI_FUNC(PyOS_sighandler_t) PyOS_setsig(int, PyOS_sighandler_t); + ++/* Random */ ++PyAPI_FUNC(int) _PyOS_URandom (void *buffer, Py_ssize_t size); + + #ifdef __cplusplus + } diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_os.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_os.py new file mode 100644 index 00000000000..f412f01da8d --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_os.py @@ -0,0 +1,31 @@ +$NetBSD: patch-CVE-2012-1150-Lib_os.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/os.py.orig 2010-01-31 16:47:55.000000000 +0000 ++++ Lib/os.py 2012-03-25 09:51:50.000000000 +0100 +@@ -742,22 +742,3 @@ + _make_statvfs_result) + except NameError: # statvfs_result may not exist + pass +- +-if not _exists("urandom"): +- def urandom(n): +- """urandom(n) -> str +- +- Return a string of n random bytes suitable for cryptographic use. +- +- """ +- try: +- _urandomfd = open("/dev/urandom", O_RDONLY) +- except (OSError, IOError): +- raise NotImplementedError("/dev/urandom (or equivalent) not found") +- try: +- bs = b"" +- while n - len(bs) >= 1: +- bs += read(_urandomfd, n - len(bs)) +- finally: +- close(_urandomfd) +- return bs diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_cmd_line.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_cmd_line.py new file mode 100644 index 00000000000..b5e723f785b --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_cmd_line.py @@ -0,0 +1,29 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_cmd_line.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_cmd_line.py.orig 2007-11-18 11:56:28.000000000 +0000 ++++ Lib/test/test_cmd_line.py 2012-03-25 09:51:50.000000000 +0100 +@@ -103,6 +103,20 @@ + self.exit_code('-c', 'pass'), + 0) + ++ def test_hash_randomization(self): ++ # Verify that -R enables hash randomization: ++ self.verify_valid_flag('-R') ++ hashes = [] ++ for i in range(2): ++ code = 'print(hash("spam"))' ++ data = self.start_python('-R', '-c', code) ++ hashes.append(data) ++ self.assertNotEqual(hashes[0], hashes[1]) ++ ++ # Verify that sys.flags contains hash_randomization ++ code = 'import sys; print sys.flags' ++ data = self.start_python('-R', '-c', code) ++ self.assertTrue('hash_randomization=1' in data) + + def test_main(): + test.test_support.run_unittest(CmdLineTest) diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_hash.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_hash.py new file mode 100644 index 00000000000..2b8be5f5308 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_hash.py @@ -0,0 +1,129 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_hash.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_hash.py.orig 2008-12-30 01:36:00.000000000 +0000 ++++ Lib/test/test_hash.py 2012-03-25 09:51:50.000000000 +0100 +@@ -3,10 +3,18 @@ + # + # Also test that hash implementations are inherited as expected + ++import os ++import sys ++import struct ++import datetime + import unittest ++import subprocess ++ + from test import test_support + from collections import Hashable + ++IS_64BIT = (struct.calcsize('l') == 8) ++ + + class HashEqualityTestCase(unittest.TestCase): + +@@ -133,10 +141,100 @@ + for obj in self.hashes_to_check: + self.assertEqual(hash(obj), _default_hash(obj)) + ++class HashRandomizationTests(unittest.TestCase): ++ ++ # Each subclass should define a field "repr_", containing the repr() of ++ # an object to be tested ++ ++ def get_hash_command(self, repr_): ++ return 'print(hash(%s))' % repr_ ++ ++ def get_hash(self, repr_, seed=None): ++ env = os.environ.copy() ++ if seed is not None: ++ env['PYTHONHASHSEED'] = str(seed) ++ else: ++ env.pop('PYTHONHASHSEED', None) ++ cmd_line = [sys.executable, '-c', self.get_hash_command(repr_)] ++ p = subprocess.Popen(cmd_line, stdin=subprocess.PIPE, ++ stdout=subprocess.PIPE, stderr=subprocess.STDOUT, ++ env=env) ++ out, err = p.communicate() ++ out = test_support.strip_python_stderr(out) ++ return int(out.strip()) ++ ++ def test_randomized_hash(self): ++ # two runs should return different hashes ++ run1 = self.get_hash(self.repr_, seed='random') ++ run2 = self.get_hash(self.repr_, seed='random') ++ self.assertNotEqual(run1, run2) ++ ++class StringlikeHashRandomizationTests(HashRandomizationTests): ++ def test_null_hash(self): ++ # PYTHONHASHSEED=0 disables the randomized hash ++ if IS_64BIT: ++ known_hash_of_obj = 1453079729188098211 ++ else: ++ known_hash_of_obj = -1600925533 ++ ++ # Randomization is disabled by default: ++ self.assertEqual(self.get_hash(self.repr_), known_hash_of_obj) ++ ++ # It can also be disabled by setting the seed to 0: ++ self.assertEqual(self.get_hash(self.repr_, seed=0), known_hash_of_obj) ++ ++ def test_fixed_hash(self): ++ # test a fixed seed for the randomized hash ++ # Note that all types share the same values: ++ if IS_64BIT: ++ h = -4410911502303878509 ++ else: ++ h = -206076799 ++ self.assertEqual(self.get_hash(self.repr_, seed=42), h) ++ ++class StrHashRandomizationTests(StringlikeHashRandomizationTests): ++ repr_ = repr('abc') ++ ++ def test_empty_string(self): ++ self.assertEqual(hash(""), 0) ++ ++class UnicodeHashRandomizationTests(StringlikeHashRandomizationTests): ++ repr_ = repr(u'abc') ++ ++ def test_empty_string(self): ++ self.assertEqual(hash(u""), 0) ++ ++class BufferHashRandomizationTests(StringlikeHashRandomizationTests): ++ repr_ = 'buffer("abc")' ++ ++ def test_empty_string(self): ++ self.assertEqual(hash(buffer("")), 0) ++ ++class DatetimeTests(HashRandomizationTests): ++ def get_hash_command(self, repr_): ++ return 'import datetime; print(hash(%s))' % repr_ ++ ++class DatetimeDateTests(DatetimeTests): ++ repr_ = repr(datetime.date(1066, 10, 14)) ++ ++class DatetimeDatetimeTests(DatetimeTests): ++ repr_ = repr(datetime.datetime(1, 2, 3, 4, 5, 6, 7)) ++ ++class DatetimeTimeTests(DatetimeTests): ++ repr_ = repr(datetime.time(0)) ++ ++ + def test_main(): + test_support.run_unittest(HashEqualityTestCase, + HashInheritanceTestCase, +- HashBuiltinsTestCase) ++ HashBuiltinsTestCase, ++ StrHashRandomizationTests, ++ UnicodeHashRandomizationTests, ++ BufferHashRandomizationTests, ++ DatetimeDateTests, ++ DatetimeDatetimeTests, ++ DatetimeTimeTests) ++ + + + if __name__ == "__main__": diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_os.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_os.py new file mode 100644 index 00000000000..dfae85a2a49 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_os.py @@ -0,0 +1,76 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_os.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_os.py.orig 2010-08-03 11:44:09.000000000 +0100 ++++ Lib/test/test_os.py 2012-03-25 09:51:50.000000000 +0100 +@@ -6,6 +6,8 @@ + import unittest + import warnings + import sys ++import subprocess ++ + from test import test_support + + warnings.filterwarnings("ignore", "tempnam", RuntimeWarning, __name__) +@@ -499,18 +501,46 @@ + + class URandomTests (unittest.TestCase): + def test_urandom(self): +- try: +- with test_support.check_warnings(): +- self.assertEqual(len(os.urandom(1)), 1) +- self.assertEqual(len(os.urandom(10)), 10) +- self.assertEqual(len(os.urandom(100)), 100) +- self.assertEqual(len(os.urandom(1000)), 1000) +- # see http://bugs.python.org/issue3708 +- self.assertEqual(len(os.urandom(0.9)), 0) +- self.assertEqual(len(os.urandom(1.1)), 1) +- self.assertEqual(len(os.urandom(2.0)), 2) +- except NotImplementedError: +- pass ++ with test_support.check_warnings(): ++ self.assertEqual(len(os.urandom(1)), 1) ++ self.assertEqual(len(os.urandom(10)), 10) ++ self.assertEqual(len(os.urandom(100)), 100) ++ self.assertEqual(len(os.urandom(1000)), 1000) ++ # see http://bugs.python.org/issue3708 ++ self.assertEqual(len(os.urandom(0.9)), 0) ++ self.assertEqual(len(os.urandom(1.1)), 1) ++ self.assertEqual(len(os.urandom(2.0)), 2) ++ ++ def test_urandom_length(self): ++ self.assertEqual(len(os.urandom(0)), 0) ++ self.assertEqual(len(os.urandom(1)), 1) ++ self.assertEqual(len(os.urandom(10)), 10) ++ self.assertEqual(len(os.urandom(100)), 100) ++ self.assertEqual(len(os.urandom(1000)), 1000) ++ ++ def test_urandom_value(self): ++ data1 = os.urandom(16) ++ data2 = os.urandom(16) ++ self.assertNotEqual(data1, data2) ++ ++ def get_urandom_subprocess(self, count): ++ code = '\n'.join(( ++ 'import os, sys', ++ 'data = os.urandom(%s)' % count, ++ 'sys.stdout.write(data)', ++ 'sys.stdout.flush()')) ++ cmd_line = [sys.executable, '-c', code] ++ p = subprocess.Popen(cmd_line, stdin=subprocess.PIPE, ++ stdout=subprocess.PIPE, stderr=subprocess.STDOUT) ++ out, err = p.communicate() ++ out = test_support.strip_python_stderr(out) ++ self.assertEqual(len(out), count) ++ return out ++ ++ def test_urandom_subprocess(self): ++ data1 = self.get_urandom_subprocess(16) ++ data2 = self.get_urandom_subprocess(16) ++ self.assertNotEqual(data1, data2) + + class Win32ErrorTests(unittest.TestCase): + def test_rename(self): diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_set.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_set.py new file mode 100644 index 00000000000..de158e85183 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_set.py @@ -0,0 +1,81 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_set.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_set.py.orig 2010-08-03 09:41:02.000000000 +0100 ++++ Lib/test/test_set.py 2012-03-25 09:51:50.000000000 +0100 +@@ -6,7 +6,6 @@ + import operator + import copy + import pickle +-import os + from random import randrange, shuffle + import sys + import collections +@@ -688,6 +687,17 @@ + if self.repr is not None: + self.assertEqual(repr(self.set), self.repr) + ++ def check_repr_against_values(self): ++ text = repr(self.set) ++ self.assertTrue(text.startswith('{')) ++ self.assertTrue(text.endswith('}')) ++ ++ result = text[1:-1].split(', ') ++ result.sort() ++ sorted_repr_values = [repr(value) for value in self.values] ++ sorted_repr_values.sort() ++ self.assertEqual(result, sorted_repr_values) ++ + def test_print(self): + fo = open(test_support.TESTFN, "wb") + try: +@@ -837,6 +847,46 @@ + self.length = 3 + self.repr = None + ++#------------------------------------------------------------------------------ ++ ++class TestBasicOpsString(TestBasicOps): ++ def setUp(self): ++ self.case = "string set" ++ self.values = ["a", "b", "c"] ++ self.set = set(self.values) ++ self.dup = set(self.values) ++ self.length = 3 ++ ++ def test_repr(self): ++ self.check_repr_against_values() ++ ++#------------------------------------------------------------------------------ ++ ++class TestBasicOpsUnicode(TestBasicOps): ++ def setUp(self): ++ self.case = "unicode set" ++ self.values = [u"a", u"b", u"c"] ++ self.set = set(self.values) ++ self.dup = set(self.values) ++ self.length = 3 ++ ++ def test_repr(self): ++ self.check_repr_against_values() ++ ++#------------------------------------------------------------------------------ ++ ++class TestBasicOpsMixedStringUnicode(TestBasicOps): ++ def setUp(self): ++ self.case = "string and bytes set" ++ self.values = ["a", "b", u"a", u"b"] ++ self.set = set(self.values) ++ self.dup = set(self.values) ++ self.length = 4 ++ ++ def test_repr(self): ++ with test_support.check_warnings(): ++ self.check_repr_against_values() ++ + #============================================================================== + + def baditer(): diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_support.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_support.py new file mode 100644 index 00000000000..ddd5a89fa41 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_support.py @@ -0,0 +1,31 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_support.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_support.py.orig 2010-08-02 23:01:34.000000000 +0100 ++++ Lib/test/test_support.py 2012-03-25 09:51:50.000000000 +0100 +@@ -24,7 +24,7 @@ + "captured_stdout", "TransientResource", "transient_internet", + "run_with_locale", "set_memlimit", "bigmemtest", "bigaddrspacetest", + "BasicTestRunner", "run_unittest", "run_doctest", "threading_setup", +- "threading_cleanup", "reap_children"] ++ "threading_cleanup", "reap_children", "strip_python_stderr"] + + class Error(Exception): + """Base class for regression test exceptions.""" +@@ -893,3 +893,13 @@ + break + except: + break ++ ++def strip_python_stderr(stderr): ++ """Strip the stderr of a Python process from potential debug output ++ emitted by the interpreter. ++ ++ This will typically be run on the result of the communicate() method ++ of a subprocess.Popen object. ++ """ ++ stderr = re.sub(br"\[\d+ refs\]\r?\n?$", b"", stderr).strip() ++ return stderr diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_symtable.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_symtable.py new file mode 100644 index 00000000000..75fe63ea444 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_symtable.py @@ -0,0 +1,23 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_symtable.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_symtable.py.orig 2010-08-03 00:34:49.000000000 +0100 ++++ Lib/test/test_symtable.py 2012-03-25 09:51:50.000000000 +0100 +@@ -105,10 +105,11 @@ + + def test_function_info(self): + func = self.spam +- self.assertEqual(func.get_parameters(), ("a", "b", "kw", "var")) +- self.assertEqual(func.get_locals(), ++ self.assertEqual( ++ tuple(sorted(func.get_parameters())), ("a", "b", "kw", "var")) ++ self.assertEqual(tuple(sorted(func.get_locals())), + ("a", "b", "bar", "internal", "kw", "var", "x")) +- self.assertEqual(func.get_globals(), ("bar", "glob")) ++ self.assertEqual(tuple(sorted(func.get_globals())), ("bar", "glob")) + self.assertEqual(self.internal.get_frees(), ("x",)) + + def test_globals(self): diff --git a/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_sys.py b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_sys.py new file mode 100644 index 00000000000..92c89de3955 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Lib_test_test_sys.py @@ -0,0 +1,17 @@ +$NetBSD: patch-CVE-2012-1150-Lib_test_test_sys.py,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Lib/test/test_sys.py.orig 2010-08-02 19:40:55.000000000 +0100 ++++ Lib/test/test_sys.py 2012-03-25 09:51:50.000000000 +0100 +@@ -384,7 +384,7 @@ + attrs = ("debug", "py3k_warning", "division_warning", "division_new", + "inspect", "interactive", "optimize", "dont_write_bytecode", + "no_site", "ignore_environment", "tabcheck", "verbose", +- "unicode", "bytes_warning") ++ "unicode", "bytes_warning", "hash_randomization") + for attr in attrs: + self.assert_(hasattr(sys.flags, attr), attr) + self.assertEqual(type(getattr(sys.flags, attr)), int, attr) diff --git a/lang/python26/patches/patch-CVE-2012-1150-Misc_NEWS b/lang/python26/patches/patch-CVE-2012-1150-Misc_NEWS new file mode 100644 index 00000000000..5045c529732 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Misc_NEWS @@ -0,0 +1,20 @@ +$NetBSD: patch-CVE-2012-1150-Misc_NEWS,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Misc/NEWS.orig 2011-06-03 22:55:45.000000000 +0100 ++++ Misc/NEWS 2012-03-25 09:51:50.000000000 +0100 +@@ -901,6 +901,11 @@ + Core and Builtins + ----------------- + ++- Issue #13703: oCERT-2011-003: add -R command-line option and PYTHONHASHSEED ++ environment variable, to provide an opt-in way to protect against denial of ++ service attacks due to hash collisions within the dict and set types. Patch ++ by David Malcolm, based on work by Victor Stinner. ++ + Library + ------- + diff --git a/lang/python26/patches/patch-CVE-2012-1150-Misc_python.man b/lang/python26/patches/patch-CVE-2012-1150-Misc_python.man new file mode 100644 index 00000000000..e9067175e74 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Misc_python.man @@ -0,0 +1,58 @@ +$NetBSD: patch-CVE-2012-1150-Misc_python.man,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Misc/python.man.orig 2010-01-31 16:09:16.000000000 +0000 ++++ Misc/python.man 2012-03-25 09:51:50.000000000 +0100 +@@ -34,6 +34,9 @@ + .B \-O0 + ] + [ ++.B \-R ++] ++[ + .B -Q + .I argument + ] +@@ -151,6 +154,18 @@ + .B \-O0 + Discard docstrings in addition to the \fB-O\fP optimizations. + .TP ++.B \-R ++Turn on "hash randomization", so that the hash() values of str, bytes and ++datetime objects are "salted" with an unpredictable pseudo-random value. ++Although they remain constant within an individual Python process, they are ++not predictable between repeated invocations of Python. ++.IP ++This is intended to provide protection against a denial of service ++caused by carefully-chosen inputs that exploit the worst case performance ++of a dict insertion, O(n^2) complexity. See ++http://www.ocert.org/advisories/ocert-2011-003.html ++for details. ++.TP + .BI "\-Q " argument + Division control; see PEP 238. The argument must be one of "old" (the + default, int/int and long/long return an int or long), "new" (new +@@ -411,6 +426,20 @@ + If this is set to a non-empty string it is equivalent to specifying + the \fB\-v\fP option. If set to an integer, it is equivalent to + specifying \fB\-v\fP multiple times. ++.IP PYTHONHASHSEED ++If this variable is set to "random", the effect is the same as specifying ++the \fB-R\fP option: a random value is used to seed the hashes of str, ++bytes and datetime objects. ++ ++If PYTHONHASHSEED is set to an integer value, it is used as a fixed seed for ++generating the hash() of the types covered by the hash randomization. Its ++purpose is to allow repeatable hashing, such as for selftests for the ++interpreter itself, or to allow a cluster of python processes to share hash ++values. ++ ++The integer must be a decimal number in the range [0,4294967295]. Specifying ++the value 0 will lead to the same hash values as when hash randomization is ++disabled. + .SH AUTHOR + The Python Software Foundation: http://www.python.org/psf + .SH INTERNET RESOURCES diff --git a/lang/python26/patches/patch-CVE-2012-1150-Modules_main.c b/lang/python26/patches/patch-CVE-2012-1150-Modules_main.c new file mode 100644 index 00000000000..44d0491b9d7 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Modules_main.c @@ -0,0 +1,59 @@ +$NetBSD: patch-CVE-2012-1150-Modules_main.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Modules/main.c.orig 2010-05-09 16:15:40.000000000 +0100 ++++ Modules/main.c 2012-03-25 09:51:50.000000000 +0100 +@@ -40,7 +40,7 @@ + static int orig_argc; + + /* command line options */ +-#define BASE_OPTS "3bBc:dEhiJm:OQ:sStuUvVW:xX?" ++#define BASE_OPTS "3bBc:dEhiJm:OQ:RsStuUvVW:xX?" + + #ifndef RISCOS + #define PROGRAM_OPTS BASE_OPTS +@@ -71,6 +71,9 @@ + -m mod : run library module as a script (terminates option list)\n\ + -O : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\ + -OO : remove doc-strings in addition to the -O optimizations\n\ ++-R : use a pseudo-random salt to make hash() values of various types be\n\ ++ unpredictable between separate invocations of the interpreter, as\n\ ++ a defense against denial-of-service attacks\n\ + -Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\ + -s : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\ + -S : don't imply 'import site' on initialization\n\ +@@ -101,6 +104,12 @@ + PYTHONCASEOK : ignore case in 'import' statements (Windows).\n\ + PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n\ + "; ++static char *usage_6 = "\ ++PYTHONHASHSEED: if this variable is set to ``random``, the effect is the same \n\ ++ as specifying the :option:`-R` option: a random value is used to seed the\n\ ++ hashes of str, bytes and datetime objects. It can also be set to an integer\n\ ++ in the range [0,4294967295] to get hash values with a predictable seed.\n\ ++"; + + + static int +@@ -117,6 +126,7 @@ + fputs(usage_3, f); + fprintf(f, usage_4, DELIM); + fprintf(f, usage_5, DELIM, PYTHONHOMEHELP); ++ fputs(usage_6, f); + } + #if defined(__VMS) + if (exitcode == 0) { +@@ -388,6 +398,10 @@ + PySys_AddWarnOption(_PyOS_optarg); + break; + ++ case 'R': ++ Py_HashRandomizationFlag++; ++ break; ++ + /* This space reserved for other options */ + + default: diff --git a/lang/python26/patches/patch-CVE-2012-1150-Modules_posixmodule.c b/lang/python26/patches/patch-CVE-2012-1150-Modules_posixmodule.c new file mode 100644 index 00000000000..19ae5dd3924 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Modules_posixmodule.c @@ -0,0 +1,157 @@ +$NetBSD: patch-CVE-2012-1150-Modules_posixmodule.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Modules/posixmodule.c.orig 2010-07-24 11:05:19.000000000 +0100 ++++ Modules/posixmodule.c 2012-03-25 09:51:50.000000000 +0100 +@@ -8371,117 +8371,35 @@ + } + #endif + +-#ifdef MS_WINDOWS +- +-PyDoc_STRVAR(win32_urandom__doc__, ++PyDoc_STRVAR(posix_urandom__doc__, + "urandom(n) -> str\n\n\ +-Return a string of n random bytes suitable for cryptographic use."); +- +-typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\ +- LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\ +- DWORD dwFlags ); +-typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\ +- BYTE *pbBuffer ); +- +-static CRYPTGENRANDOM pCryptGenRandom = NULL; +-/* This handle is never explicitly released. Instead, the operating +- system will release it when the process terminates. */ +-static HCRYPTPROV hCryptProv = 0; ++Return n random bytes suitable for cryptographic use."); + +-static PyObject* +-win32_urandom(PyObject *self, PyObject *args) ++static PyObject * ++posix_urandom(PyObject *self, PyObject *args) + { +- int howMany; +- PyObject* result; ++ Py_ssize_t size; ++ PyObject *result; ++ int ret; + +- /* Read arguments */ +- if (! PyArg_ParseTuple(args, "i:urandom", &howMany)) ++ /* Read arguments */ ++ if (!PyArg_ParseTuple(args, "n:urandom", &size)) + return NULL; +- if (howMany < 0) ++ if (size < 0) + return PyErr_Format(PyExc_ValueError, + "negative argument not allowed"); +- +- if (hCryptProv == 0) { +- HINSTANCE hAdvAPI32 = NULL; +- CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL; +- +- /* Obtain handle to the DLL containing CryptoAPI +- This should not fail */ +- hAdvAPI32 = GetModuleHandle("advapi32.dll"); +- if(hAdvAPI32 == NULL) +- return win32_error("GetModuleHandle", NULL); +- +- /* Obtain pointers to the CryptoAPI functions +- This will fail on some early versions of Win95 */ +- pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress( +- hAdvAPI32, +- "CryptAcquireContextA"); +- if (pCryptAcquireContext == NULL) +- return PyErr_Format(PyExc_NotImplementedError, +- "CryptAcquireContextA not found"); +- +- pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress( +- hAdvAPI32, "CryptGenRandom"); +- if (pCryptGenRandom == NULL) +- return PyErr_Format(PyExc_NotImplementedError, +- "CryptGenRandom not found"); +- +- /* Acquire context */ +- if (! pCryptAcquireContext(&hCryptProv, NULL, NULL, +- PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) +- return win32_error("CryptAcquireContext", NULL); +- } +- +- /* Allocate bytes */ +- result = PyString_FromStringAndSize(NULL, howMany); +- if (result != NULL) { +- /* Get random data */ +- memset(PyString_AS_STRING(result), 0, howMany); /* zero seed */ +- if (! pCryptGenRandom(hCryptProv, howMany, (unsigned char*) +- PyString_AS_STRING(result))) { +- Py_DECREF(result); +- return win32_error("CryptGenRandom", NULL); +- } +- } +- return result; +-} +-#endif +- +-#ifdef __VMS +-/* Use openssl random routine */ +-#include <openssl/rand.h> +-PyDoc_STRVAR(vms_urandom__doc__, +-"urandom(n) -> str\n\n\ +-Return a string of n random bytes suitable for cryptographic use."); +- +-static PyObject* +-vms_urandom(PyObject *self, PyObject *args) +-{ +- int howMany; +- PyObject* result; +- +- /* Read arguments */ +- if (! PyArg_ParseTuple(args, "i:urandom", &howMany)) ++ result = PyBytes_FromStringAndSize(NULL, size); ++ if (result == NULL) + return NULL; +- if (howMany < 0) +- return PyErr_Format(PyExc_ValueError, +- "negative argument not allowed"); + +- /* Allocate bytes */ +- result = PyString_FromStringAndSize(NULL, howMany); +- if (result != NULL) { +- /* Get random data */ +- if (RAND_pseudo_bytes((unsigned char*) +- PyString_AS_STRING(result), +- howMany) < 0) { +- Py_DECREF(result); +- return PyErr_Format(PyExc_ValueError, +- "RAND_pseudo_bytes"); +- } ++ ret = _PyOS_URandom(PyBytes_AS_STRING(result), ++ PyBytes_GET_SIZE(result)); ++ if (ret == -1) { ++ Py_DECREF(result); ++ return NULL; + } + return result; + } +-#endif + + static PyMethodDef posix_methods[] = { + {"access", posix_access, METH_VARARGS, posix_access__doc__}, +@@ -8787,12 +8705,7 @@ + #ifdef HAVE_GETLOADAVG + {"getloadavg", posix_getloadavg, METH_NOARGS, posix_getloadavg__doc__}, + #endif +- #ifdef MS_WINDOWS +- {"urandom", win32_urandom, METH_VARARGS, win32_urandom__doc__}, +- #endif +- #ifdef __VMS +- {"urandom", vms_urandom, METH_VARARGS, vms_urandom__doc__}, +- #endif ++ {"urandom", posix_urandom, METH_VARARGS, posix_urandom__doc__}, + {NULL, NULL} /* Sentinel */ + }; + diff --git a/lang/python26/patches/patch-CVE-2012-1150-Objects_bufferobject.c b/lang/python26/patches/patch-CVE-2012-1150-Objects_bufferobject.c new file mode 100644 index 00000000000..5aefb23b929 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Objects_bufferobject.c @@ -0,0 +1,30 @@ +$NetBSD: patch-CVE-2012-1150-Objects_bufferobject.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Objects/bufferobject.c.orig 2010-05-09 16:15:40.000000000 +0100 ++++ Objects/bufferobject.c 2012-03-25 09:51:50.000000000 +0100 +@@ -334,10 +334,20 @@ + return -1; + p = (unsigned char *) ptr; + len = size; +- x = *p << 7; ++ /* ++ We make the hash of the empty buffer be 0, rather than using ++ (prefix ^ suffix), since this slightly obfuscates the hash secret ++ */ ++ if (len == 0) { ++ self->b_hash = 0; ++ return 0; ++ } ++ x = _Py_HashSecret.prefix; ++ x ^= *p << 7; + while (--len >= 0) + x = (1000003*x) ^ *p++; + x ^= size; ++ x ^= _Py_HashSecret.suffix; + if (x == -1) + x = -2; + self->b_hash = x; diff --git a/lang/python26/patches/patch-CVE-2012-1150-Objects_object.c b/lang/python26/patches/patch-CVE-2012-1150-Objects_object.c new file mode 100644 index 00000000000..6746705c236 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Objects_object.c @@ -0,0 +1,17 @@ +$NetBSD: patch-CVE-2012-1150-Objects_object.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Objects/object.c.orig 2010-05-09 16:15:40.000000000 +0100 ++++ Objects/object.c 2012-03-25 09:51:50.000000000 +0100 +@@ -1101,6 +1101,8 @@ + return -1; + } + ++_Py_HashSecret_t _Py_HashSecret; ++ + long + PyObject_Hash(PyObject *v) + { diff --git a/lang/python26/patches/patch-CVE-2012-1150-Objects_stringobject.c b/lang/python26/patches/patch-CVE-2012-1150-Objects_stringobject.c new file mode 100644 index 00000000000..38d2d579c5e --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Objects_stringobject.c @@ -0,0 +1,31 @@ +$NetBSD: patch-CVE-2012-1150-Objects_stringobject.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Objects/stringobject.c.orig 2010-08-01 23:02:09.000000000 +0100 ++++ Objects/stringobject.c 2012-03-25 09:51:50.000000000 +0100 +@@ -1212,11 +1212,21 @@ + if (a->ob_shash != -1) + return a->ob_shash; + len = Py_SIZE(a); ++ /* ++ We make the hash of the empty string be 0, rather than using ++ (prefix ^ suffix), since this slightly obfuscates the hash secret ++ */ ++ if (len == 0) { ++ a->ob_shash = 0; ++ return 0; ++ } + p = (unsigned char *) a->ob_sval; +- x = *p << 7; ++ x = _Py_HashSecret.prefix; ++ x ^= *p << 7; + while (--len >= 0) + x = (1000003*x) ^ *p++; + x ^= Py_SIZE(a); ++ x ^= _Py_HashSecret.suffix; + if (x == -1) + x = -2; + a->ob_shash = x; diff --git a/lang/python26/patches/patch-CVE-2012-1150-Objects_unicodeobject.c b/lang/python26/patches/patch-CVE-2012-1150-Objects_unicodeobject.c new file mode 100644 index 00000000000..df0cd62265e --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Objects_unicodeobject.c @@ -0,0 +1,31 @@ +$NetBSD: patch-CVE-2012-1150-Objects_unicodeobject.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Objects/unicodeobject.c.orig 2010-08-01 22:48:47.000000000 +0100 ++++ Objects/unicodeobject.c 2012-03-25 09:51:50.000000000 +0100 +@@ -6695,11 +6695,21 @@ + if (self->hash != -1) + return self->hash; + len = PyUnicode_GET_SIZE(self); ++ /* ++ We make the hash of the empty string be 0, rather than using ++ (prefix ^ suffix), since this slightly obfuscates the hash secret ++ */ ++ if (len == 0) { ++ self->hash = 0; ++ return 0; ++ } + p = PyUnicode_AS_UNICODE(self); +- x = *p << 7; ++ x = _Py_HashSecret.prefix; ++ x ^= *p << 7; + while (--len >= 0) + x = (1000003*x) ^ *p++; + x ^= PyUnicode_GET_SIZE(self); ++ x ^= _Py_HashSecret.suffix; + if (x == -1) + x = -2; + self->hash = x; diff --git a/lang/python26/patches/patch-CVE-2012-1150-PCbuild_pythoncore.vcproj b/lang/python26/patches/patch-CVE-2012-1150-PCbuild_pythoncore.vcproj new file mode 100644 index 00000000000..49befb1352c --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-PCbuild_pythoncore.vcproj @@ -0,0 +1,19 @@ +$NetBSD: patch-CVE-2012-1150-PCbuild_pythoncore.vcproj,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- PCbuild/pythoncore.vcproj.orig 2008-06-10 22:23:22.000000000 +0100 ++++ PCbuild/pythoncore.vcproj 2012-03-25 09:51:50.000000000 +0100 +@@ -1779,6 +1779,10 @@ + > + </File> + <File ++ RelativePath="..\Python\random.c" ++ > ++ </File> ++ <File + RelativePath="..\Python\structmember.c" + > + </File> diff --git a/lang/python26/patches/patch-CVE-2012-1150-Python_pythonrun.c b/lang/python26/patches/patch-CVE-2012-1150-Python_pythonrun.c new file mode 100644 index 00000000000..1f43d303369 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Python_pythonrun.c @@ -0,0 +1,37 @@ +$NetBSD: patch-CVE-2012-1150-Python_pythonrun.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Python/pythonrun.c.orig 2010-05-25 23:40:38.000000000 +0100 ++++ Python/pythonrun.c 2012-03-25 09:51:50.000000000 +0100 +@@ -67,6 +67,7 @@ + static void call_ll_exitfuncs(void); + extern void _PyUnicode_Init(void); + extern void _PyUnicode_Fini(void); ++extern void _PyRandom_Init(void); + + #ifdef WITH_THREAD + extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); +@@ -89,6 +90,7 @@ + true divisions (which they will be in 2.3). */ + int _Py_QnewFlag = 0; + int Py_NoUserSiteDirectory = 0; /* for -s and site.py */ ++int Py_HashRandomizationFlag = 0; /* for -R and PYTHONHASHSEED */ + + /* PyModule_GetWarningsModule is no longer necessary as of 2.6 + since _warnings is builtin. This API should not be used. */ +@@ -166,6 +168,12 @@ + Py_OptimizeFlag = add_flag(Py_OptimizeFlag, p); + if ((p = Py_GETENV("PYTHONDONTWRITEBYTECODE")) && *p != '\0') + Py_DontWriteBytecodeFlag = add_flag(Py_DontWriteBytecodeFlag, p); ++ /* The variable is only tested for existence here; _PyRandom_Init will ++ check its value further. */ ++ if ((p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0') ++ Py_HashRandomizationFlag = add_flag(Py_HashRandomizationFlag, p); ++ ++ _PyRandom_Init(); + + interp = PyInterpreterState_New(); + if (interp == NULL) diff --git a/lang/python26/patches/patch-CVE-2012-1150-Python_random.c b/lang/python26/patches/patch-CVE-2012-1150-Python_random.c new file mode 100644 index 00000000000..5ba60d6abe1 --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Python_random.c @@ -0,0 +1,311 @@ +$NetBSD: patch-CVE-2012-1150-Python_random.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Python/random.c.orig 2012-03-25 09:51:50.000000000 +0100 ++++ Python/random.c 2012-03-25 09:51:50.000000000 +0100 +@@ -0,0 +1,302 @@ ++#include "Python.h" ++#ifdef MS_WINDOWS ++#include <windows.h> ++#else ++#include <fcntl.h> ++#endif ++ ++static int random_initialized = 0; ++ ++#ifdef MS_WINDOWS ++typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv,\ ++ LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType,\ ++ DWORD dwFlags ); ++typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen,\ ++ BYTE *pbBuffer ); ++ ++static CRYPTGENRANDOM pCryptGenRandom = NULL; ++/* This handle is never explicitly released. Instead, the operating ++ system will release it when the process terminates. */ ++static HCRYPTPROV hCryptProv = 0; ++ ++static int ++win32_urandom_init(int raise) ++{ ++ HINSTANCE hAdvAPI32 = NULL; ++ CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL; ++ ++ /* Obtain handle to the DLL containing CryptoAPI. This should not fail. */ ++ hAdvAPI32 = GetModuleHandle("advapi32.dll"); ++ if(hAdvAPI32 == NULL) ++ goto error; ++ ++ /* Obtain pointers to the CryptoAPI functions. This will fail on some early ++ versions of Win95. */ ++ pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress( ++ hAdvAPI32, "CryptAcquireContextA"); ++ if (pCryptAcquireContext == NULL) ++ goto error; ++ ++ pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, ++ "CryptGenRandom"); ++ if (pCryptGenRandom == NULL) ++ goto error; ++ ++ /* Acquire context */ ++ if (! pCryptAcquireContext(&hCryptProv, NULL, NULL, ++ PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) ++ goto error; ++ ++ return 0; ++ ++error: ++ if (raise) ++ PyErr_SetFromWindowsErr(0); ++ else ++ Py_FatalError("Failed to initialize Windows random API (CryptoGen)"); ++ return -1; ++} ++ ++/* Fill buffer with size pseudo-random bytes generated by the Windows CryptoGen ++ API. Return 0 on success, or -1 on error. */ ++static int ++win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) ++{ ++ Py_ssize_t chunk; ++ ++ if (hCryptProv == 0) ++ { ++ if (win32_urandom_init(raise) == -1) ++ return -1; ++ } ++ ++ while (size > 0) ++ { ++ chunk = size > INT_MAX ? INT_MAX : size; ++ if (!pCryptGenRandom(hCryptProv, chunk, buffer)) ++ { ++ /* CryptGenRandom() failed */ ++ if (raise) ++ PyErr_SetFromWindowsErr(0); ++ else ++ Py_FatalError("Failed to initialized the randomized hash " ++ "secret using CryptoGen)"); ++ return -1; ++ } ++ buffer += chunk; ++ size -= chunk; ++ } ++ return 0; ++} ++#endif /* MS_WINDOWS */ ++ ++ ++#ifdef __VMS ++/* Use openssl random routine */ ++#include <openssl/rand.h> ++static int ++vms_urandom(unsigned char *buffer, Py_ssize_t size, int raise) ++{ ++ if (RAND_pseudo_bytes(buffer, size) < 0) { ++ if (raise) { ++ PyErr_Format(PyExc_ValueError, ++ "RAND_pseudo_bytes"); ++ } else { ++ Py_FatalError("Failed to initialize the randomized hash " ++ "secret using RAND_pseudo_bytes"); ++ } ++ return -1; ++ } ++ return 0; ++} ++#endif /* __VMS */ ++ ++ ++#if !defined(MS_WINDOWS) && !defined(__VMS) ++ ++/* Read size bytes from /dev/urandom into buffer. ++ Call Py_FatalError() on error. */ ++static void ++dev_urandom_noraise(char *buffer, Py_ssize_t size) ++{ ++ int fd; ++ Py_ssize_t n; ++ ++ assert (0 < size); ++ ++ fd = open("/dev/urandom", O_RDONLY); ++ if (fd < 0) ++ Py_FatalError("Failed to open /dev/urandom"); ++ ++ while (0 < size) ++ { ++ do { ++ n = read(fd, buffer, (size_t)size); ++ } while (n < 0 && errno == EINTR); ++ if (n <= 0) ++ { ++ /* stop on error or if read(size) returned 0 */ ++ Py_FatalError("Failed to read bytes from /dev/urandom"); ++ break; ++ } ++ buffer += n; ++ size -= (Py_ssize_t)n; ++ } ++ close(fd); ++} ++ ++/* Read size bytes from /dev/urandom into buffer. ++ Return 0 on success, raise an exception and return -1 on error. */ ++static int ++dev_urandom_python(char *buffer, Py_ssize_t size) ++{ ++ int fd; ++ Py_ssize_t n; ++ ++ if (size <= 0) ++ return 0; ++ ++ Py_BEGIN_ALLOW_THREADS ++ fd = open("/dev/urandom", O_RDONLY); ++ Py_END_ALLOW_THREADS ++ if (fd < 0) ++ { ++ PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/urandom"); ++ return -1; ++ } ++ ++ Py_BEGIN_ALLOW_THREADS ++ do { ++ do { ++ n = read(fd, buffer, (size_t)size); ++ } while (n < 0 && errno == EINTR); ++ if (n <= 0) ++ break; ++ buffer += n; ++ size -= (Py_ssize_t)n; ++ } while (0 < size); ++ Py_END_ALLOW_THREADS ++ ++ if (n <= 0) ++ { ++ /* stop on error or if read(size) returned 0 */ ++ if (n < 0) ++ PyErr_SetFromErrno(PyExc_OSError); ++ else ++ PyErr_Format(PyExc_RuntimeError, ++ "Failed to read %zi bytes from /dev/urandom", ++ size); ++ close(fd); ++ return -1; ++ } ++ close(fd); ++ return 0; ++} ++#endif /* !defined(MS_WINDOWS) && !defined(__VMS) */ ++ ++/* Fill buffer with pseudo-random bytes generated by a linear congruent ++ generator (LCG): ++ ++ x(n+1) = (x(n) * 214013 + 2531011) % 2^32 ++ ++ Use bits 23..16 of x(n) to generate a byte. */ ++static void ++lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size) ++{ ++ size_t index; ++ unsigned int x; ++ ++ x = x0; ++ for (index=0; index < size; index++) { ++ x *= 214013; ++ x += 2531011; ++ /* modulo 2 ^ (8 * sizeof(int)) */ ++ buffer[index] = (x >> 16) & 0xff; ++ } ++} ++ ++/* Fill buffer with size pseudo-random bytes, not suitable for cryptographic ++ use, from the operating random number generator (RNG). ++ ++ Return 0 on success, raise an exception and return -1 on error. */ ++int ++_PyOS_URandom(void *buffer, Py_ssize_t size) ++{ ++ if (size < 0) { ++ PyErr_Format(PyExc_ValueError, ++ "negative argument not allowed"); ++ return -1; ++ } ++ if (size == 0) ++ return 0; ++ ++#ifdef MS_WINDOWS ++ return win32_urandom((unsigned char *)buffer, size, 1); ++#else ++# ifdef __VMS ++ return vms_urandom((unsigned char *)buffer, size, 1); ++# else ++ return dev_urandom_python((char*)buffer, size); ++# endif ++#endif ++} ++ ++void ++_PyRandom_Init(void) ++{ ++ char *env; ++ void *secret = &_Py_HashSecret; ++ Py_ssize_t secret_size = sizeof(_Py_HashSecret); ++ ++ if (random_initialized) ++ return; ++ random_initialized = 1; ++ ++ /* ++ By default, hash randomization is disabled, and only ++ enabled if PYTHONHASHSEED is set to non-empty or if ++ "-R" is provided at the command line: ++ */ ++ if (!Py_HashRandomizationFlag) { ++ /* Disable the randomized hash: */ ++ memset(secret, 0, secret_size); ++ return; ++ } ++ ++ /* ++ Hash randomization is enabled. Generate a per-process secret, ++ using PYTHONHASHSEED if provided. ++ */ ++ ++ env = Py_GETENV("PYTHONHASHSEED"); ++ if (env && *env != '\0' && strcmp(env, "random") != 0) { ++ char *endptr = env; ++ unsigned long seed; ++ seed = strtoul(env, &endptr, 10); ++ if (*endptr != '\0' ++ || seed > 4294967295UL ++ || (errno == ERANGE && seed == ULONG_MAX)) ++ { ++ Py_FatalError("PYTHONHASHSEED must be \"random\" or an integer " ++ "in range [0; 4294967295]"); ++ } ++ if (seed == 0) { ++ /* disable the randomized hash */ ++ memset(secret, 0, secret_size); ++ } ++ else { ++ lcg_urandom(seed, (unsigned char*)secret, secret_size); ++ } ++ } ++ else { ++#ifdef MS_WINDOWS ++ (void)win32_urandom((unsigned char *)secret, secret_size, 0); ++#else /* #ifdef MS_WINDOWS */ ++# ifdef __VMS ++ vms_urandom((unsigned char *)secret, secret_size, 0); ++# else ++ dev_urandom_noraise((char*)secret, secret_size); ++# endif ++#endif ++ } ++} diff --git a/lang/python26/patches/patch-CVE-2012-1150-Python_sysmodule.c b/lang/python26/patches/patch-CVE-2012-1150-Python_sysmodule.c new file mode 100644 index 00000000000..851ccfaa59e --- /dev/null +++ b/lang/python26/patches/patch-CVE-2012-1150-Python_sysmodule.c @@ -0,0 +1,36 @@ +$NetBSD: patch-CVE-2012-1150-Python_sysmodule.c,v 1.1 2012/03/25 09:09:05 tron Exp $ + +Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +--- Python/sysmodule.c.orig 2010-05-21 18:22:43.000000000 +0100 ++++ Python/sysmodule.c 2012-03-25 09:51:50.000000000 +0100 +@@ -1224,6 +1224,7 @@ + {"unicode", "-U"}, + /* {"skip_first", "-x"}, */ + {"bytes_warning", "-b"}, ++ {"hash_randomization", "-R"}, + {0} + }; + +@@ -1232,9 +1233,9 @@ + flags__doc__, /* doc */ + flags_fields, /* fields */ + #ifdef RISCOS +- 16 ++ 17 + #else +- 15 ++ 16 + #endif + }; + +@@ -1271,6 +1272,7 @@ + SetFlag(Py_UnicodeFlag); + /* SetFlag(skipfirstline); */ + SetFlag(Py_BytesWarningFlag); ++ SetFlag(Py_HashRandomizationFlag); + #undef SetFlag + + if (PyErr_Occurred()) { diff --git a/lang/python26/patches/patch-au b/lang/python26/patches/patch-au index e9368875589..48c1d1ba7b8 100644 --- a/lang/python26/patches/patch-au +++ b/lang/python26/patches/patch-au @@ -1,5 +1,30 @@ -$NetBSD: patch-au,v 1.7 2010/09/22 09:13:48 obache Exp $ +$NetBSD: patch-au,v 1.8 2012/03/25 09:09:05 tron Exp $ +1.) Fix for CVE-2012-1150 taken from here: + +http://hg.python.org/cpython/rev/6b7704fe1be1 + +2.) Fix for unpriviliged build. + +--- Makefile.pre.in.orig 2012-03-25 09:49:52.000000000 +0100 ++++ Makefile.pre.in 2012-03-25 09:51:50.000000000 +0100 +@@ -280,6 +280,7 @@ + Python/pymath.o \ + Python/pystate.o \ + Python/pythonrun.o \ ++ Python/random.o \ + Python/structmember.o \ + Python/symtable.o \ + Python/sysmodule.o \ +@@ -708,7 +709,7 @@ + -@if which pybuildbot.identify >/dev/null 2>&1; then \ + pybuildbot.identify "CC='$(CC)'" "CXX='$(CXX)'"; \ + fi +- $(TESTPYTHON) $(TESTPROG) -uall -rw $(TESTOPTS) ++ $(TESTPYTHON) -R $(TESTPROG) -uall -rw $(TESTOPTS) + + QUICKTESTOPTS= $(TESTOPTS) -x test_thread test_signal test_strftime \ + test_unicodedata test_re test_sre test_select test_poll \ --- Makefile.pre.in.orig 2010-08-01 22:05:31.000000000 +0000 +++ Makefile.pre.in @@ -785,7 +785,8 @@ altbininstall: $(BUILDPYTHON) |