diff options
Diffstat (limited to 'meta/recipes-devtools/python/python3')
| -rw-r--r-- | meta/recipes-devtools/python/python3/0001-Do-not-use-the-shell-version-of-python-config-that-w.patch | 10 | ||||
| -rw-r--r-- | meta/recipes-devtools/python/python3/0001-cross-compile-support.patch (renamed from meta/recipes-devtools/python/python3/000-cross-compile.patch) | 56 | ||||
| -rw-r--r-- | meta/recipes-devtools/python/python3/python3-fix-CVE-2016-1000110.patch | 148 | ||||
| -rw-r--r-- | meta/recipes-devtools/python/python3/upstream-random-fixes.patch | 288 |
4 files changed, 172 insertions, 330 deletions
diff --git a/meta/recipes-devtools/python/python3/0001-Do-not-use-the-shell-version-of-python-config-that-w.patch b/meta/recipes-devtools/python/python3/0001-Do-not-use-the-shell-version-of-python-config-that-w.patch index b7e0ac6354..8ea3f03fe0 100644 --- a/meta/recipes-devtools/python/python3/0001-Do-not-use-the-shell-version-of-python-config-that-w.patch +++ b/meta/recipes-devtools/python/python3/0001-Do-not-use-the-shell-version-of-python-config-that-w.patch | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | From 045c99b5f1eb6e4e0d8ad1ef9f0ba6574f738150 Mon Sep 17 00:00:00 2001 | 1 | From 04df959365e2b54d7503edf0e5534ff094284f2d Mon Sep 17 00:00:00 2001 |
| 2 | From: Alexander Kanavin <alex.kanavin@gmail.com> | 2 | From: Alexander Kanavin <alex.kanavin@gmail.com> |
| 3 | Date: Fri, 23 Oct 2015 12:25:09 +0300 | 3 | Date: Fri, 23 Oct 2015 12:25:09 +0300 |
| 4 | Subject: [PATCH] Do not use the shell version of python-config that was | 4 | Subject: [PATCH] Do not use the shell version of python-config that was |
| @@ -14,13 +14,13 @@ Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com> | |||
| 14 | 1 file changed, 3 insertions(+), 6 deletions(-) | 14 | 1 file changed, 3 insertions(+), 6 deletions(-) |
| 15 | 15 | ||
| 16 | diff --git a/Makefile.pre.in b/Makefile.pre.in | 16 | diff --git a/Makefile.pre.in b/Makefile.pre.in |
| 17 | index d7fc9a0..47e60bc 100644 | 17 | index 236f005..5c4337f 100644 |
| 18 | --- a/Makefile.pre.in | 18 | --- a/Makefile.pre.in |
| 19 | +++ b/Makefile.pre.in | 19 | +++ b/Makefile.pre.in |
| 20 | @@ -1270,12 +1270,9 @@ python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh | 20 | @@ -1348,12 +1348,9 @@ python-config: $(srcdir)/Misc/python-config.in Misc/python-config.sh |
| 21 | sed -e "s,@EXENAME@,$(BINDIR)/python$(LDVERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config.py | 21 | sed -e "s,@EXENAME@,$(BINDIR)/python$(LDVERSION)$(EXE)," < $(srcdir)/Misc/python-config.in >python-config.py |
| 22 | # Replace makefile compat. variable references with shell script compat. ones; $(VAR) -> ${VAR} | 22 | # Replace makefile compat. variable references with shell script compat. ones; $(VAR) -> ${VAR} |
| 23 | sed -e 's,\$$(\([A-Za-z0-9_]*\)),\$$\{\1\},g' < Misc/python-config.sh >python-config | 23 | LC_ALL=C sed -e 's,\$$(\([A-Za-z0-9_]*\)),\$$\{\1\},g' < Misc/python-config.sh >python-config |
| 24 | - # On Darwin, always use the python version of the script, the shell | 24 | - # On Darwin, always use the python version of the script, the shell |
| 25 | - # version doesn't use the compiler customizations that are provided | 25 | - # version doesn't use the compiler customizations that are provided |
| 26 | - # in python (_osx_support.py). | 26 | - # in python (_osx_support.py). |
| @@ -34,5 +34,5 @@ index d7fc9a0..47e60bc 100644 | |||
| 34 | 34 | ||
| 35 | # Install the include files | 35 | # Install the include files |
| 36 | -- | 36 | -- |
| 37 | 2.1.4 | 37 | 2.11.0 |
| 38 | 38 | ||
diff --git a/meta/recipes-devtools/python/python3/000-cross-compile.patch b/meta/recipes-devtools/python/python3/0001-cross-compile-support.patch index 2d822218f4..118d75ddc5 100644 --- a/meta/recipes-devtools/python/python3/000-cross-compile.patch +++ b/meta/recipes-devtools/python/python3/0001-cross-compile-support.patch | |||
| @@ -1,27 +1,32 @@ | |||
| 1 | From 624c029abcc73c724020ccea9a2b4b5b5c00f2a6 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Alexander Kanavin <alex.kanavin@gmail.com> | ||
| 3 | Date: Fri, 31 Mar 2017 15:42:46 +0300 | ||
| 4 | Subject: [PATCH] cross-compile support | ||
| 5 | |||
| 1 | We cross compile python. This patch uses tools from host/native | 6 | We cross compile python. This patch uses tools from host/native |
| 2 | python instead of in-tree tools | 7 | python instead of in-tree tools |
| 3 | 8 | ||
| 4 | -Khem | 9 | -Khem |
| 5 | 10 | ||
| 6 | Upstream-Status: Inappropriate[Configuration Specific] | 11 | Upstream-Status: Inappropriate[Configuration Specific] |
| 7 | 12 | Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com> | |
| 8 | --- | 13 | --- |
| 9 | Makefile.pre.in | 25 +++++++++++++------------ | 14 | Makefile.pre.in | 14 ++++++++------ |
| 10 | 1 file changed, 13 insertions(+), 12 deletions(-) | 15 | 1 file changed, 8 insertions(+), 6 deletions(-) |
| 11 | 16 | ||
| 12 | Index: Python-3.5.2/Makefile.pre.in | 17 | diff --git a/Makefile.pre.in b/Makefile.pre.in |
| 13 | =================================================================== | 18 | index a88b7d5..7cb8bb3 100644 |
| 14 | --- Python-3.5.2.orig/Makefile.pre.in | 19 | --- a/Makefile.pre.in |
| 15 | +++ Python-3.5.2/Makefile.pre.in | 20 | +++ b/Makefile.pre.in |
| 16 | @@ -220,6 +220,7 @@ LIBOBJS= @LIBOBJS@ | 21 | @@ -221,6 +221,7 @@ LIBOBJS= @LIBOBJS@ |
| 17 | 22 | ||
| 18 | PYTHON= python$(EXE) | 23 | PYTHON= python$(EXE) |
| 19 | BUILDPYTHON= python$(BUILDEXE) | 24 | BUILDPYTHON= python$(BUILDEXE) |
| 20 | +HOSTPYTHON= $(BUILDPYTHON) | 25 | +HOSTPYTHON= $(BUILDPYTHON) |
| 21 | 26 | ||
| 22 | cross_compiling=@cross_compiling@ | 27 | PYTHON_FOR_GEN=@PYTHON_FOR_GEN@ |
| 23 | PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@ | 28 | PYTHON_FOR_BUILD=@PYTHON_FOR_BUILD@ |
| 24 | @@ -279,6 +280,7 @@ LIBFFI_INCLUDEDIR= @LIBFFI_INCLUDEDIR@ | 29 | @@ -280,6 +281,7 @@ LIBFFI_INCLUDEDIR= @LIBFFI_INCLUDEDIR@ |
| 25 | ########################################################################## | 30 | ########################################################################## |
| 26 | # Parser | 31 | # Parser |
| 27 | PGEN= Parser/pgen$(EXE) | 32 | PGEN= Parser/pgen$(EXE) |
| @@ -29,7 +34,7 @@ Index: Python-3.5.2/Makefile.pre.in | |||
| 29 | 34 | ||
| 30 | PSRCS= \ | 35 | PSRCS= \ |
| 31 | Parser/acceler.c \ | 36 | Parser/acceler.c \ |
| 32 | @@ -509,7 +511,7 @@ build_all_generate_profile: | 37 | @@ -510,7 +512,7 @@ build_all_generate_profile: |
| 33 | 38 | ||
| 34 | run_profile_task: | 39 | run_profile_task: |
| 35 | : # FIXME: can't run for a cross build | 40 | : # FIXME: can't run for a cross build |
| @@ -38,16 +43,16 @@ Index: Python-3.5.2/Makefile.pre.in | |||
| 38 | 43 | ||
| 39 | build_all_merge_profile: | 44 | build_all_merge_profile: |
| 40 | $(LLVM_PROF_MERGER) | 45 | $(LLVM_PROF_MERGER) |
| 41 | @@ -792,7 +794,7 @@ $(GRAMMAR_H): $(GRAMMAR_INPUT) $(PGEN) | 46 | @@ -787,7 +789,7 @@ $(IO_OBJS): $(IO_H) |
| 47 | |||
| 48 | $(GRAMMAR_H): @GENERATED_COMMENT@ $(GRAMMAR_INPUT) $(PGEN) | ||
| 42 | @$(MKDIR_P) Include | 49 | @$(MKDIR_P) Include |
| 43 | # Avoid copying the file onto itself for an in-tree build | 50 | - $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) |
| 44 | if test "$(cross_compiling)" != "yes"; then \ | 51 | + $(HOSTPGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C) |
| 45 | - $(PGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C); \ | 52 | $(GRAMMAR_C): @GENERATED_COMMENT@ $(GRAMMAR_H) |
| 46 | + $(HOSTPGEN) $(GRAMMAR_INPUT) $(GRAMMAR_H) $(GRAMMAR_C); \ | 53 | touch $(GRAMMAR_C) |
| 47 | else \ | 54 | |
| 48 | cp $(srcdir)/Include/graminit.h $(GRAMMAR_H).tmp; \ | 55 | @@ -976,7 +978,7 @@ $(LIBRARY_OBJS) $(MODOBJS) Programs/python.o: $(PYTHON_HEADERS) |
| 49 | mv $(GRAMMAR_H).tmp $(GRAMMAR_H); \ | ||
| 50 | @@ -990,7 +992,7 @@ $(LIBRARY_OBJS) $(MODOBJS) Programs/pyth | ||
| 51 | ###################################################################### | 56 | ###################################################################### |
| 52 | 57 | ||
| 53 | TESTOPTS= $(EXTRATESTOPTS) | 58 | TESTOPTS= $(EXTRATESTOPTS) |
| @@ -56,7 +61,7 @@ Index: Python-3.5.2/Makefile.pre.in | |||
| 56 | TESTRUNNER= $(TESTPYTHON) $(srcdir)/Tools/scripts/run_tests.py | 61 | TESTRUNNER= $(TESTPYTHON) $(srcdir)/Tools/scripts/run_tests.py |
| 57 | TESTTIMEOUT= 3600 | 62 | TESTTIMEOUT= 3600 |
| 58 | 63 | ||
| 59 | @@ -1481,7 +1483,7 @@ frameworkinstallstructure: $(LDLIBRARY) | 64 | @@ -1468,7 +1470,7 @@ frameworkinstallstructure: $(LDLIBRARY) |
| 60 | fi; \ | 65 | fi; \ |
| 61 | done | 66 | done |
| 62 | $(LN) -fsn include/python$(LDVERSION) $(DESTDIR)$(prefix)/Headers | 67 | $(LN) -fsn include/python$(LDVERSION) $(DESTDIR)$(prefix)/Headers |
| @@ -65,7 +70,7 @@ Index: Python-3.5.2/Makefile.pre.in | |||
| 65 | $(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current | 70 | $(LN) -fsn $(VERSION) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Versions/Current |
| 66 | $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK) | 71 | $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/$(PYTHONFRAMEWORK) |
| 67 | $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers | 72 | $(LN) -fsn Versions/Current/Headers $(DESTDIR)$(PYTHONFRAMEWORKINSTALLDIR)/Headers |
| 68 | @@ -1547,7 +1549,7 @@ config.status: $(srcdir)/configure | 73 | @@ -1534,7 +1536,7 @@ config.status: $(srcdir)/configure |
| 69 | 74 | ||
| 70 | # Run reindent on the library | 75 | # Run reindent on the library |
| 71 | reindent: | 76 | reindent: |
| @@ -74,7 +79,7 @@ Index: Python-3.5.2/Makefile.pre.in | |||
| 74 | 79 | ||
| 75 | # Rerun configure with the same options as it was run last time, | 80 | # Rerun configure with the same options as it was run last time, |
| 76 | # provided the config.status script exists | 81 | # provided the config.status script exists |
| 77 | @@ -1683,7 +1685,7 @@ funny: | 82 | @@ -1674,7 +1676,7 @@ funny: |
| 78 | 83 | ||
| 79 | # Perform some verification checks on any modified files. | 84 | # Perform some verification checks on any modified files. |
| 80 | patchcheck: all | 85 | patchcheck: all |
| @@ -83,3 +88,6 @@ Index: Python-3.5.2/Makefile.pre.in | |||
| 83 | 88 | ||
| 84 | # Dependencies | 89 | # Dependencies |
| 85 | 90 | ||
| 91 | -- | ||
| 92 | 2.11.0 | ||
| 93 | |||
diff --git a/meta/recipes-devtools/python/python3/python3-fix-CVE-2016-1000110.patch b/meta/recipes-devtools/python/python3/python3-fix-CVE-2016-1000110.patch deleted file mode 100644 index ab1b7230ea..0000000000 --- a/meta/recipes-devtools/python/python3/python3-fix-CVE-2016-1000110.patch +++ /dev/null | |||
| @@ -1,148 +0,0 @@ | |||
| 1 | From aab3e8c432b90508ac14755128f5a687be2fdf43 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Mingli Yu <Mingli.Yu@windriver.com> | ||
| 3 | Date: Thu, 22 Sep 2016 16:39:49 +0800 | ||
| 4 | Subject: [PATCH] python3: fix CVE-2016-1000110 | ||
| 5 | MIME-Version: 1.0 | ||
| 6 | Content-Type: text/plain; charset=UTF-8 | ||
| 7 | Content-Transfer-Encoding: 8bit | ||
| 8 | |||
| 9 | Ignore the HTTP_PROXY variable when REQUEST_METHOD environment is set, which | ||
| 10 | indicates that the script is in CGI mode. | ||
| 11 | |||
| 12 | Issue #27568 Reported and patch contributed by Rémi Rampin. [#27568] | ||
| 13 | |||
| 14 | Backport patch from https://hg.python.org/cpython/rev/a0ac52ed8f79 | ||
| 15 | |||
| 16 | Upstream-Status: Backport | ||
| 17 | CVE: CVE-2016-1000110 | ||
| 18 | Signed-off-by: Mingli Yu <Mingli.Yu@windriver.com> | ||
| 19 | --- | ||
| 20 | Doc/howto/urllib2.rst | 5 +++++ | ||
| 21 | Doc/library/urllib.request.rst | 17 ++++++++++++++++- | ||
| 22 | Lib/test/test_urllib.py | 14 +++++++++++++- | ||
| 23 | Lib/urllib/request.py | 6 ++++++ | ||
| 24 | Misc/NEWS | 4 ++++ | ||
| 25 | 5 files changed, 44 insertions(+), 2 deletions(-) | ||
| 26 | |||
| 27 | diff --git a/Doc/howto/urllib2.rst b/Doc/howto/urllib2.rst | ||
| 28 | index 24a4156..d2c7991 100644 | ||
| 29 | --- a/Doc/howto/urllib2.rst | ||
| 30 | +++ b/Doc/howto/urllib2.rst | ||
| 31 | @@ -538,6 +538,11 @@ setting up a `Basic Authentication`_ handler: :: | ||
| 32 | through a proxy. However, this can be enabled by extending urllib.request as | ||
| 33 | shown in the recipe [#]_. | ||
| 34 | |||
| 35 | +.. note:: | ||
| 36 | + | ||
| 37 | + ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; see | ||
| 38 | + the documentation on :func:`~urllib.request.getproxies`. | ||
| 39 | + | ||
| 40 | |||
| 41 | Sockets and Layers | ||
| 42 | ================== | ||
| 43 | diff --git a/Doc/library/urllib.request.rst b/Doc/library/urllib.request.rst | ||
| 44 | index 1338906..1291aeb 100644 | ||
| 45 | --- a/Doc/library/urllib.request.rst | ||
| 46 | +++ b/Doc/library/urllib.request.rst | ||
| 47 | @@ -173,6 +173,16 @@ The :mod:`urllib.request` module defines the following functions: | ||
| 48 | If both lowercase and uppercase environment variables exist (and disagree), | ||
| 49 | lowercase is preferred. | ||
| 50 | |||
| 51 | + .. note:: | ||
| 52 | + | ||
| 53 | + If the environment variable ``REQUEST_METHOD`` is set, which usually | ||
| 54 | + indicates your script is running in a CGI environment, the environment | ||
| 55 | + variable ``HTTP_PROXY`` (uppercase ``_PROXY``) will be ignored. This is | ||
| 56 | + because that variable can be injected by a client using the "Proxy:" HTTP | ||
| 57 | + header. If you need to use an HTTP proxy in a CGI environment, either use | ||
| 58 | + ``ProxyHandler`` explicitly, or make sure the variable name is in | ||
| 59 | + lowercase (or at least the ``_proxy`` suffix). | ||
| 60 | + | ||
| 61 | |||
| 62 | The following classes are provided: | ||
| 63 | |||
| 64 | @@ -280,6 +290,11 @@ The following classes are provided: | ||
| 65 | list of hostname suffixes, optionally with ``:port`` appended, for example | ||
| 66 | ``cern.ch,ncsa.uiuc.edu,some.host:8080``. | ||
| 67 | |||
| 68 | + .. note:: | ||
| 69 | + | ||
| 70 | + ``HTTP_PROXY`` will be ignored if a variable ``REQUEST_METHOD`` is set; | ||
| 71 | + see the documentation on :func:`~urllib.request.getproxies`. | ||
| 72 | + | ||
| 73 | |||
| 74 | .. class:: HTTPPasswordMgr() | ||
| 75 | |||
| 76 | @@ -1138,7 +1153,7 @@ the returned bytes object to string once it determines or guesses | ||
| 77 | the appropriate encoding. | ||
| 78 | |||
| 79 | The following W3C document, https://www.w3.org/International/O-charset\ , lists | ||
| 80 | -the various ways in which a (X)HTML or a XML document could have specified its | ||
| 81 | +the various ways in which an (X)HTML or an XML document could have specified its | ||
| 82 | encoding information. | ||
| 83 | |||
| 84 | As the python.org website uses *utf-8* encoding as specified in its meta tag, we | ||
| 85 | diff --git a/Lib/test/test_urllib.py b/Lib/test/test_urllib.py | ||
| 86 | index 5d05f8d..247598a 100644 | ||
| 87 | --- a/Lib/test/test_urllib.py | ||
| 88 | +++ b/Lib/test/test_urllib.py | ||
| 89 | @@ -1,4 +1,4 @@ | ||
| 90 | -"""Regresssion tests for what was in Python 2's "urllib" module""" | ||
| 91 | +"""Regression tests for what was in Python 2's "urllib" module""" | ||
| 92 | |||
| 93 | import urllib.parse | ||
| 94 | import urllib.request | ||
| 95 | @@ -232,6 +232,18 @@ class ProxyTests(unittest.TestCase): | ||
| 96 | self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com:8888')) | ||
| 97 | self.assertTrue(urllib.request.proxy_bypass_environment('newdomain.com:1234')) | ||
| 98 | |||
| 99 | + def test_proxy_cgi_ignore(self): | ||
| 100 | + try: | ||
| 101 | + self.env.set('HTTP_PROXY', 'http://somewhere:3128') | ||
| 102 | + proxies = urllib.request.getproxies_environment() | ||
| 103 | + self.assertEqual('http://somewhere:3128', proxies['http']) | ||
| 104 | + self.env.set('REQUEST_METHOD', 'GET') | ||
| 105 | + proxies = urllib.request.getproxies_environment() | ||
| 106 | + self.assertNotIn('http', proxies) | ||
| 107 | + finally: | ||
| 108 | + self.env.unset('REQUEST_METHOD') | ||
| 109 | + self.env.unset('HTTP_PROXY') | ||
| 110 | + | ||
| 111 | def test_proxy_bypass_environment_host_match(self): | ||
| 112 | bypass = urllib.request.proxy_bypass_environment | ||
| 113 | self.env.set('NO_PROXY', | ||
| 114 | diff --git a/Lib/urllib/request.py b/Lib/urllib/request.py | ||
| 115 | index 1731fe3..3be327d 100644 | ||
| 116 | --- a/Lib/urllib/request.py | ||
| 117 | +++ b/Lib/urllib/request.py | ||
| 118 | @@ -2412,6 +2412,12 @@ def getproxies_environment(): | ||
| 119 | name = name.lower() | ||
| 120 | if value and name[-6:] == '_proxy': | ||
| 121 | proxies[name[:-6]] = value | ||
| 122 | + # CVE-2016-1000110 - If we are running as CGI script, forget HTTP_PROXY | ||
| 123 | + # (non-all-lowercase) as it may be set from the web server by a "Proxy:" | ||
| 124 | + # header from the client | ||
| 125 | + # If "proxy" is lowercase, it will still be used thanks to the next block | ||
| 126 | + if 'REQUEST_METHOD' in os.environ: | ||
| 127 | + proxies.pop('http', None) | ||
| 128 | for name, value in os.environ.items(): | ||
| 129 | if name[-6:] == '_proxy': | ||
| 130 | name = name.lower() | ||
| 131 | diff --git a/Misc/NEWS b/Misc/NEWS | ||
| 132 | index 4ad2551..2fcc95b 100644 | ||
| 133 | --- a/Misc/NEWS | ||
| 134 | +++ b/Misc/NEWS | ||
| 135 | @@ -329,6 +329,10 @@ Library | ||
| 136 | - Issue #26644: Raise ValueError rather than SystemError when a negative | ||
| 137 | length is passed to SSLSocket.recv() or read(). | ||
| 138 | |||
| 139 | +- Issue #27568: Prevent HTTPoxy attack (CVE-2016-1000110). Ignore the | ||
| 140 | + HTTP_PROXY variable when REQUEST_METHOD environment is set, which indicates | ||
| 141 | + that the script is in CGI mode. | ||
| 142 | + | ||
| 143 | - Issue #23804: Fix SSL recv(0) and read(0) methods to return zero bytes | ||
| 144 | instead of up to 1024. | ||
| 145 | |||
| 146 | -- | ||
| 147 | 2.8.1 | ||
| 148 | |||
diff --git a/meta/recipes-devtools/python/python3/upstream-random-fixes.patch b/meta/recipes-devtools/python/python3/upstream-random-fixes.patch index 0d9152ccd7..9b40e8ac9f 100644 --- a/meta/recipes-devtools/python/python3/upstream-random-fixes.patch +++ b/meta/recipes-devtools/python/python3/upstream-random-fixes.patch | |||
| @@ -1,21 +1,7 @@ | |||
| 1 | This patch updates random.c to match upstream python's code at revision | 1 | From 035ba5da3e53e45c712b39fe1f6fb743e697c032 Mon Sep 17 00:00:00 2001 |
| 2 | 8125d9a8152b. This addresses various issues around problems with glibc 2.24 | 2 | From: Victor Stinner <victor.stinner@gmail.com> |
| 3 | and 2.25 such that python would fail to start with: | 3 | Date: Mon, 9 Jan 2017 11:18:53 +0100 |
| 4 | 4 | Subject: [PATCH] Issue #29157: Prefer getrandom() over getentropy() | |
| 5 | [rpurdie@centos7 ~]$ /tmp/t2/sysroots/x86_64-pokysdk-linux/usr/bin/python3 | ||
| 6 | Fatal Python error: getentropy() failed | ||
| 7 | Aborted | ||
| 8 | |||
| 9 | (taken from our buildtools-tarball also breaks eSDK) | ||
| 10 | |||
| 11 | Upstream-Status: Backport | ||
| 12 | |||
| 13 | # HG changeset patch | ||
| 14 | # User Victor Stinner <victor.stinner@gmail.com> | ||
| 15 | # Date 1483957133 -3600 | ||
| 16 | # Node ID 8125d9a8152b79e712cb09c7094b9129b9bcea86 | ||
| 17 | # Parent 337461574c90281630751b6095c4e1baf380cf7d | ||
| 18 | Issue #29157: Prefer getrandom() over getentropy() | ||
| 19 | 5 | ||
| 20 | Copy and then adapt Python/random.c from default branch. Difference between 3.5 | 6 | Copy and then adapt Python/random.c from default branch. Difference between 3.5 |
| 21 | and default branches: | 7 | and default branches: |
| @@ -26,12 +12,17 @@ and default branches: | |||
| 26 | * Python 3.5 has no _PyOS_URandomNonblock() function: _PyOS_URandom() | 12 | * Python 3.5 has no _PyOS_URandomNonblock() function: _PyOS_URandom() |
| 27 | works in non-blocking mode on Python 3.5 | 13 | works in non-blocking mode on Python 3.5 |
| 28 | 14 | ||
| 29 | RP 2017/1/22 | 15 | Upstream-Status: Backport [https://github.com/python/cpython/commit/035ba5da3e53e45c712b39fe1f6fb743e697c032] |
| 16 | Signed-off-by: Alexander Kanavin <alexander.kanavin@intel.com> | ||
| 17 | |||
| 18 | --- | ||
| 19 | Python/random.c | 494 +++++++++++++++++++++++++++++++++----------------------- | ||
| 20 | 1 file changed, 294 insertions(+), 200 deletions(-) | ||
| 30 | 21 | ||
| 31 | Index: Python-3.5.2/Python/random.c | 22 | diff --git a/Python/random.c b/Python/random.c |
| 32 | =================================================================== | 23 | index d203939..31f61d0 100644 |
| 33 | --- Python-3.5.2.orig/Python/random.c | 24 | --- a/Python/random.c |
| 34 | +++ Python-3.5.2/Python/random.c | 25 | +++ b/Python/random.c |
| 35 | @@ -1,6 +1,9 @@ | 26 | @@ -1,6 +1,9 @@ |
| 36 | #include "Python.h" | 27 | #include "Python.h" |
| 37 | #ifdef MS_WINDOWS | 28 | #ifdef MS_WINDOWS |
| @@ -42,7 +33,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 42 | #else | 33 | #else |
| 43 | # include <fcntl.h> | 34 | # include <fcntl.h> |
| 44 | # ifdef HAVE_SYS_STAT_H | 35 | # ifdef HAVE_SYS_STAT_H |
| 45 | @@ -36,10 +39,9 @@ win32_urandom_init(int raise) | 36 | @@ -37,10 +40,9 @@ win32_urandom_init(int raise) |
| 46 | return 0; | 37 | return 0; |
| 47 | 38 | ||
| 48 | error: | 39 | error: |
| @@ -55,7 +46,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 55 | return -1; | 46 | return -1; |
| 56 | } | 47 | } |
| 57 | 48 | ||
| 58 | @@ -52,8 +54,9 @@ win32_urandom(unsigned char *buffer, Py_ | 49 | @@ -53,8 +55,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) |
| 59 | 50 | ||
| 60 | if (hCryptProv == 0) | 51 | if (hCryptProv == 0) |
| 61 | { | 52 | { |
| @@ -66,7 +57,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 66 | } | 57 | } |
| 67 | 58 | ||
| 68 | while (size > 0) | 59 | while (size > 0) |
| 69 | @@ -62,11 +65,9 @@ win32_urandom(unsigned char *buffer, Py_ | 60 | @@ -63,11 +66,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) |
| 70 | if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) | 61 | if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) |
| 71 | { | 62 | { |
| 72 | /* CryptGenRandom() failed */ | 63 | /* CryptGenRandom() failed */ |
| @@ -80,7 +71,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 80 | return -1; | 71 | return -1; |
| 81 | } | 72 | } |
| 82 | buffer += chunk; | 73 | buffer += chunk; |
| 83 | @@ -75,55 +76,29 @@ win32_urandom(unsigned char *buffer, Py_ | 74 | @@ -76,58 +77,23 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) |
| 84 | return 0; | 75 | return 0; |
| 85 | } | 76 | } |
| 86 | 77 | ||
| @@ -129,13 +120,19 @@ Index: Python-3.5.2/Python/random.c | |||
| 129 | #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) | 120 | #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) |
| 130 | #define PY_GETRANDOM 1 | 121 | #define PY_GETRANDOM 1 |
| 131 | 122 | ||
| 123 | -/* Call getrandom() | ||
| 132 | +/* Call getrandom() to get random bytes: | 124 | +/* Call getrandom() to get random bytes: |
| 133 | + | 125 | + |
| 134 | + - Return 1 on success | 126 | - Return 1 on success |
| 127 | - - Return 0 if getrandom() syscall is not available (failed with ENOSYS or | ||
| 128 | - EPERM) or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom | ||
| 129 | - not initialized yet) and raise=0. | ||
| 135 | + - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM), | 130 | + - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM), |
| 136 | + or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not | 131 | + or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not |
| 137 | + initialized yet). | 132 | + initialized yet). |
| 138 | + - Raise an exception (if raise is non-zero) and return -1 on error: | 133 | - Raise an exception (if raise is non-zero) and return -1 on error: |
| 134 | - getrandom() failed with EINTR and the Python signal handler raised an | ||
| 135 | - exception, or getrandom() failed with a different error. */ | ||
| 139 | + if getrandom() failed with EINTR, raise is non-zero and the Python signal | 136 | + if getrandom() failed with EINTR, raise is non-zero and the Python signal |
| 140 | + handler raised an exception, or if getrandom() failed with a different | 137 | + handler raised an exception, or if getrandom() failed with a different |
| 141 | + error. | 138 | + error. |
| @@ -144,26 +141,16 @@ Index: Python-3.5.2/Python/random.c | |||
| 144 | static int | 141 | static int |
| 145 | py_getrandom(void *buffer, Py_ssize_t size, int raise) | 142 | py_getrandom(void *buffer, Py_ssize_t size, int raise) |
| 146 | { | 143 | { |
| 147 | - /* Is getrandom() supported by the running kernel? | 144 | @@ -142,16 +108,19 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
| 148 | - * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */ | ||
| 149 | + /* Is getrandom() supported by the running kernel? Set to 0 if getrandom() | ||
| 150 | + failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris | ||
| 151 | + 11.3 or newer */ | ||
| 152 | static int getrandom_works = 1; | ||
| 153 | |||
| 154 | /* getrandom() on Linux will block if called before the kernel has | ||
| 155 | @@ -132,84 +107,165 @@ py_getrandom(void *buffer, Py_ssize_t si | ||
| 156 | * see https://bugs.python.org/issue26839. To avoid this, use the | 145 | * see https://bugs.python.org/issue26839. To avoid this, use the |
| 157 | * GRND_NONBLOCK flag. */ | 146 | * GRND_NONBLOCK flag. */ |
| 158 | const int flags = GRND_NONBLOCK; | 147 | const int flags = GRND_NONBLOCK; |
| 159 | - int n; | ||
| 160 | + char *dest; | 148 | + char *dest; |
| 161 | + long n; | 149 | long n; |
| 162 | 150 | ||
| 163 | - if (!getrandom_works) | 151 | if (!getrandom_works) { |
| 164 | + if (!getrandom_works) { | ||
| 165 | return 0; | 152 | return 0; |
| 166 | + } | 153 | } |
| 167 | 154 | ||
| 168 | + dest = buffer; | 155 | + dest = buffer; |
| 169 | while (0 < size) { | 156 | while (0 < size) { |
| @@ -174,11 +161,8 @@ Index: Python-3.5.2/Python/random.c | |||
| 174 | + requested. */ | 161 | + requested. */ |
| 175 | n = Py_MIN(size, 1024); | 162 | n = Py_MIN(size, 1024); |
| 176 | #else | 163 | #else |
| 177 | - n = size; | 164 | n = Py_MIN(size, LONG_MAX); |
| 178 | + n = Py_MIN(size, LONG_MAX); | 165 | @@ -161,34 +130,35 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
| 179 | #endif | ||
| 180 | |||
| 181 | errno = 0; | ||
| 182 | #ifdef HAVE_GETRANDOM | 166 | #ifdef HAVE_GETRANDOM |
| 183 | if (raise) { | 167 | if (raise) { |
| 184 | Py_BEGIN_ALLOW_THREADS | 168 | Py_BEGIN_ALLOW_THREADS |
| @@ -209,56 +193,45 @@ Index: Python-3.5.2/Python/random.c | |||
| 209 | #endif | 193 | #endif |
| 210 | 194 | ||
| 211 | if (n < 0) { | 195 | if (n < 0) { |
| 212 | - if (errno == ENOSYS) { | 196 | - /* ENOSYS: getrandom() syscall not supported by the kernel (but |
| 197 | - * maybe supported by the host which built Python). EPERM: | ||
| 198 | - * getrandom() syscall blocked by SECCOMP or something else. */ | ||
| 213 | + /* ENOSYS: the syscall is not supported by the kernel. | 199 | + /* ENOSYS: the syscall is not supported by the kernel. |
| 214 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) | 200 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) |
| 215 | + or something else. */ | 201 | + or something else. */ |
| 216 | + if (errno == ENOSYS || errno == EPERM) { | 202 | if (errno == ENOSYS || errno == EPERM) { |
| 217 | getrandom_works = 0; | 203 | getrandom_works = 0; |
| 218 | return 0; | 204 | return 0; |
| 219 | } | 205 | } |
| 220 | + | 206 | + |
| 221 | if (errno == EAGAIN) { | 207 | if (errno == EAGAIN) { |
| 222 | - /* If we failed with EAGAIN, the entropy pool was | 208 | /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system |
| 223 | - * uninitialized. In this case, we return failure to fall | 209 | urandom is not initialiazed yet. In this case, fall back on |
| 224 | - * back to reading from /dev/urandom. | 210 | @@ -202,169 +172,225 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
| 225 | - * | ||
| 226 | - * Note: In this case the data read will not be random so | ||
| 227 | - * should not be used for cryptographic purposes. Retaining | ||
| 228 | - * the existing semantics for practical purposes. */ | ||
| 229 | + /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system | ||
| 230 | + urandom is not initialiazed yet. In this case, fall back on | ||
| 231 | + reading from /dev/urandom. | ||
| 232 | + | ||
| 233 | + Note: In this case the data read will not be random so | ||
| 234 | + should not be used for cryptographic purposes. Retaining | ||
| 235 | + the existing semantics for practical purposes. */ | ||
| 236 | getrandom_works = 0; | ||
| 237 | return 0; | ||
| 238 | } | 211 | } |
| 239 | 212 | ||
| 240 | if (errno == EINTR) { | 213 | if (errno == EINTR) { |
| 241 | - if (PyErr_CheckSignals()) { | 214 | - if (PyErr_CheckSignals()) { |
| 242 | - if (!raise) | 215 | - if (!raise) { |
| 243 | - Py_FatalError("getrandom() interrupted by a signal"); | 216 | - Py_FatalError("getrandom() interrupted by a signal"); |
| 244 | - return -1; | ||
| 245 | + if (raise) { | 217 | + if (raise) { |
| 246 | + if (PyErr_CheckSignals()) { | 218 | + if (PyErr_CheckSignals()) { |
| 247 | + return -1; | 219 | + return -1; |
| 248 | + } | 220 | } |
| 221 | - return -1; | ||
| 249 | } | 222 | } |
| 223 | |||
| 250 | - /* retry getrandom() */ | 224 | - /* retry getrandom() */ |
| 251 | + | ||
| 252 | + /* retry getrandom() if it was interrupted by a signal */ | 225 | + /* retry getrandom() if it was interrupted by a signal */ |
| 253 | continue; | 226 | continue; |
| 254 | } | 227 | } |
| 255 | 228 | ||
| 256 | - if (raise) | 229 | if (raise) { |
| 257 | + if (raise) { | ||
| 258 | PyErr_SetFromErrno(PyExc_OSError); | 230 | PyErr_SetFromErrno(PyExc_OSError); |
| 259 | - else | 231 | } |
| 232 | - else { | ||
| 260 | - Py_FatalError("getrandom() failed"); | 233 | - Py_FatalError("getrandom() failed"); |
| 261 | + } | 234 | - } |
| 262 | return -1; | 235 | return -1; |
| 263 | } | 236 | } |
| 264 | 237 | ||
| @@ -269,12 +242,19 @@ Index: Python-3.5.2/Python/random.c | |||
| 269 | return 1; | 242 | return 1; |
| 270 | } | 243 | } |
| 271 | -#endif | 244 | -#endif |
| 272 | + | 245 | |
| 246 | -static struct { | ||
| 247 | - int fd; | ||
| 248 | - dev_t st_dev; | ||
| 249 | - ino_t st_ino; | ||
| 250 | -} urandom_cache = { -1 }; | ||
| 273 | +#elif defined(HAVE_GETENTROPY) | 251 | +#elif defined(HAVE_GETENTROPY) |
| 274 | +#define PY_GETENTROPY 1 | 252 | +#define PY_GETENTROPY 1 |
| 275 | + | 253 | |
| 276 | +/* Fill buffer with size pseudo-random bytes generated by getentropy(): | 254 | +/* Fill buffer with size pseudo-random bytes generated by getentropy(): |
| 277 | + | 255 | |
| 256 | -/* Read 'size' random bytes from py_getrandom(). Fall back on reading from | ||
| 257 | - /dev/urandom if getrandom() is not available. | ||
| 278 | + - Return 1 on success | 258 | + - Return 1 on success |
| 279 | + - Return 0 if getentropy() syscall is not available (failed with ENOSYS or | 259 | + - Return 0 if getentropy() syscall is not available (failed with ENOSYS or |
| 280 | + EPERM). | 260 | + EPERM). |
| @@ -282,25 +262,47 @@ Index: Python-3.5.2/Python/random.c | |||
| 282 | + if getentropy() failed with EINTR, raise is non-zero and the Python signal | 262 | + if getentropy() failed with EINTR, raise is non-zero and the Python signal |
| 283 | + handler raised an exception, or if getentropy() failed with a different | 263 | + handler raised an exception, or if getentropy() failed with a different |
| 284 | + error. | 264 | + error. |
| 285 | + | 265 | |
| 266 | - Call Py_FatalError() on error. */ | ||
| 267 | -static void | ||
| 268 | -dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) | ||
| 286 | + getentropy() is retried if it failed with EINTR: interrupted by a signal. */ | 269 | + getentropy() is retried if it failed with EINTR: interrupted by a signal. */ |
| 287 | +static int | 270 | +static int |
| 288 | +py_getentropy(char *buffer, Py_ssize_t size, int raise) | 271 | +py_getentropy(char *buffer, Py_ssize_t size, int raise) |
| 289 | +{ | 272 | { |
| 273 | - int fd; | ||
| 274 | - Py_ssize_t n; | ||
| 290 | + /* Is getentropy() supported by the running kernel? Set to 0 if | 275 | + /* Is getentropy() supported by the running kernel? Set to 0 if |
| 291 | + getentropy() failed with ENOSYS or EPERM. */ | 276 | + getentropy() failed with ENOSYS or EPERM. */ |
| 292 | + static int getentropy_works = 1; | 277 | + static int getentropy_works = 1; |
| 293 | + | 278 | |
| 279 | - assert (0 < size); | ||
| 280 | - | ||
| 281 | -#ifdef PY_GETRANDOM | ||
| 282 | - if (py_getrandom(buffer, size, 0) == 1) { | ||
| 283 | - return; | ||
| 294 | + if (!getentropy_works) { | 284 | + if (!getentropy_works) { |
| 295 | + return 0; | 285 | + return 0; |
| 296 | + } | 286 | } |
| 297 | + | 287 | - /* getrandom() failed with ENOSYS or EPERM, |
| 288 | - fall back on reading /dev/urandom */ | ||
| 289 | -#endif | ||
| 290 | |||
| 291 | - fd = _Py_open_noraise("/dev/urandom", O_RDONLY); | ||
| 292 | - if (fd < 0) { | ||
| 293 | - Py_FatalError("Failed to open /dev/urandom"); | ||
| 294 | - } | ||
| 298 | + while (size > 0) { | 295 | + while (size > 0) { |
| 299 | + /* getentropy() is limited to returning up to 256 bytes. Call it | 296 | + /* getentropy() is limited to returning up to 256 bytes. Call it |
| 300 | + multiple times if more bytes are requested. */ | 297 | + multiple times if more bytes are requested. */ |
| 301 | + Py_ssize_t len = Py_MIN(size, 256); | 298 | + Py_ssize_t len = Py_MIN(size, 256); |
| 302 | + int res; | 299 | + int res; |
| 303 | + | 300 | |
| 301 | - while (0 < size) | ||
| 302 | - { | ||
| 303 | - do { | ||
| 304 | - n = read(fd, buffer, (size_t)size); | ||
| 305 | - } while (n < 0 && errno == EINTR); | ||
| 304 | + if (raise) { | 306 | + if (raise) { |
| 305 | + Py_BEGIN_ALLOW_THREADS | 307 | + Py_BEGIN_ALLOW_THREADS |
| 306 | + res = getentropy(buffer, len); | 308 | + res = getentropy(buffer, len); |
| @@ -309,7 +311,11 @@ Index: Python-3.5.2/Python/random.c | |||
| 309 | + else { | 311 | + else { |
| 310 | + res = getentropy(buffer, len); | 312 | + res = getentropy(buffer, len); |
| 311 | + } | 313 | + } |
| 312 | + | 314 | |
| 315 | - if (n <= 0) { | ||
| 316 | - /* read() failed or returned 0 bytes */ | ||
| 317 | - Py_FatalError("Failed to read bytes from /dev/urandom"); | ||
| 318 | - break; | ||
| 313 | + if (res < 0) { | 319 | + if (res < 0) { |
| 314 | + /* ENOSYS: the syscall is not supported by the running kernel. | 320 | + /* ENOSYS: the syscall is not supported by the running kernel. |
| 315 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) | 321 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) |
| @@ -334,71 +340,44 @@ Index: Python-3.5.2/Python/random.c | |||
| 334 | + PyErr_SetFromErrno(PyExc_OSError); | 340 | + PyErr_SetFromErrno(PyExc_OSError); |
| 335 | + } | 341 | + } |
| 336 | + return -1; | 342 | + return -1; |
| 337 | + } | 343 | } |
| 344 | - buffer += n; | ||
| 345 | - size -= n; | ||
| 338 | + | 346 | + |
| 339 | + buffer += len; | 347 | + buffer += len; |
| 340 | + size -= len; | 348 | + size -= len; |
| 341 | + } | 349 | } |
| 350 | - close(fd); | ||
| 342 | + return 1; | 351 | + return 1; |
| 343 | +} | 352 | } |
| 344 | +#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */ | 353 | +#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */ |
| 345 | + | ||
| 346 | 354 | ||
| 347 | static struct { | 355 | -/* Read 'size' random bytes from py_getrandom(). Fall back on reading from |
| 348 | int fd; | 356 | - /dev/urandom if getrandom() is not available. |
| 349 | @@ -217,127 +273,123 @@ static struct { | ||
| 350 | ino_t st_ino; | ||
| 351 | } urandom_cache = { -1 }; | ||
| 352 | 357 | ||
| 358 | - Return 0 on success. Raise an exception and return -1 on error. */ | ||
| 359 | +static struct { | ||
| 360 | + int fd; | ||
| 361 | + dev_t st_dev; | ||
| 362 | + ino_t st_ino; | ||
| 363 | +} urandom_cache = { -1 }; | ||
| 364 | + | ||
| 353 | +/* Read random bytes from the /dev/urandom device: | 365 | +/* Read random bytes from the /dev/urandom device: |
| 354 | 366 | + | |
| 355 | -/* Read size bytes from /dev/urandom into buffer. | ||
| 356 | - Call Py_FatalError() on error. */ | ||
| 357 | -static void | ||
| 358 | -dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) | ||
| 359 | -{ | ||
| 360 | - int fd; | ||
| 361 | - Py_ssize_t n; | ||
| 362 | + - Return 0 on success | 367 | + - Return 0 on success |
| 363 | + - Raise an exception (if raise is non-zero) and return -1 on error | 368 | + - Raise an exception (if raise is non-zero) and return -1 on error |
| 364 | 369 | + | |
| 365 | - assert (0 < size); | ||
| 366 | + Possible causes of errors: | 370 | + Possible causes of errors: |
| 367 | 371 | + | |
| 368 | -#ifdef PY_GETRANDOM | ||
| 369 | - if (py_getrandom(buffer, size, 0) == 1) | ||
| 370 | - return; | ||
| 371 | - /* getrandom() is not supported by the running kernel, fall back | ||
| 372 | - * on reading /dev/urandom */ | ||
| 373 | -#endif | ||
| 374 | + - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device | 372 | + - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device |
| 375 | + was not found. For example, it was removed manually or not exposed in a | 373 | + was not found. For example, it was removed manually or not exposed in a |
| 376 | + chroot or container. | 374 | + chroot or container. |
| 377 | + - open() failed with a different error | 375 | + - open() failed with a different error |
| 378 | + - fstat() failed | 376 | + - fstat() failed |
| 379 | + - read() failed or returned 0 | 377 | + - read() failed or returned 0 |
| 380 | 378 | + | |
| 381 | - fd = _Py_open_noraise("/dev/urandom", O_RDONLY); | ||
| 382 | - if (fd < 0) | ||
| 383 | - Py_FatalError("Failed to open /dev/urandom"); | ||
| 384 | + read() is retried if it failed with EINTR: interrupted by a signal. | 379 | + read() is retried if it failed with EINTR: interrupted by a signal. |
| 385 | 380 | + | |
| 386 | - while (0 < size) | ||
| 387 | - { | ||
| 388 | - do { | ||
| 389 | - n = read(fd, buffer, (size_t)size); | ||
| 390 | - } while (n < 0 && errno == EINTR); | ||
| 391 | - if (n <= 0) | ||
| 392 | - { | ||
| 393 | - /* stop on error or if read(size) returned 0 */ | ||
| 394 | - Py_FatalError("Failed to read bytes from /dev/urandom"); | ||
| 395 | - break; | ||
| 396 | - } | ||
| 397 | - buffer += n; | ||
| 398 | - size -= (Py_ssize_t)n; | ||
| 399 | - } | ||
| 400 | - close(fd); | ||
| 401 | -} | ||
| 402 | + The file descriptor of the device is kept open between calls to avoid using | 381 | + The file descriptor of the device is kept open between calls to avoid using |
| 403 | + many file descriptors when run in parallel from multiple threads: | 382 | + many file descriptors when run in parallel from multiple threads: |
| 404 | + see the issue #18756. | 383 | + see the issue #18756. |
| @@ -406,9 +385,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 406 | + st_dev and st_ino fields of the file descriptor (from fstat()) are cached to | 385 | + st_dev and st_ino fields of the file descriptor (from fstat()) are cached to |
| 407 | + check if the file descriptor was replaced by a different file (which is | 386 | + check if the file descriptor was replaced by a different file (which is |
| 408 | + likely a bug in the application): see the issue #21207. | 387 | + likely a bug in the application): see the issue #21207. |
| 409 | 388 | + | |
| 410 | -/* Read size bytes from /dev/urandom into buffer. | ||
| 411 | - Return 0 on success, raise an exception and return -1 on error. */ | ||
| 412 | + If the file descriptor was closed or replaced, open a new file descriptor | 389 | + If the file descriptor was closed or replaced, open a new file descriptor |
| 413 | + but don't close the old file descriptor: it probably points to something | 390 | + but don't close the old file descriptor: it probably points to something |
| 414 | + important for some third-party code. */ | 391 | + important for some third-party code. */ |
| @@ -422,22 +399,24 @@ Index: Python-3.5.2/Python/random.c | |||
| 422 | -#ifdef PY_GETRANDOM | 399 | -#ifdef PY_GETRANDOM |
| 423 | - int res; | 400 | - int res; |
| 424 | -#endif | 401 | -#endif |
| 425 | 402 | - | |
| 426 | - if (size <= 0) | 403 | - if (size <= 0) |
| 427 | - return 0; | 404 | - return 0; |
| 428 | + if (raise) { | ||
| 429 | + struct _Py_stat_struct st; | ||
| 430 | 405 | ||
| 431 | -#ifdef PY_GETRANDOM | 406 | -#ifdef PY_GETRANDOM |
| 432 | - res = py_getrandom(buffer, size, 1); | 407 | - res = py_getrandom(buffer, size, 1); |
| 433 | - if (res < 0) | 408 | - if (res < 0) { |
| 434 | - return -1; | 409 | - return -1; |
| 435 | - if (res == 1) | 410 | - } |
| 411 | - if (res == 1) { | ||
| 436 | - return 0; | 412 | - return 0; |
| 437 | - /* getrandom() is not supported by the running kernel, fall back | 413 | - } |
| 438 | - * on reading /dev/urandom */ | 414 | - /* getrandom() failed with ENOSYS or EPERM, |
| 415 | - fall back on reading /dev/urandom */ | ||
| 439 | -#endif | 416 | -#endif |
| 440 | - | 417 | + if (raise) { |
| 418 | + struct _Py_stat_struct st; | ||
| 419 | |||
| 441 | - if (urandom_cache.fd >= 0) { | 420 | - if (urandom_cache.fd >= 0) { |
| 442 | - /* Does the fd point to the same thing as before? (issue #21207) */ | 421 | - /* Does the fd point to the same thing as before? (issue #21207) */ |
| 443 | - if (_Py_fstat_noraise(urandom_cache.fd, &st) | 422 | - if (_Py_fstat_noraise(urandom_cache.fd, &st) |
| @@ -516,8 +495,9 @@ Index: Python-3.5.2/Python/random.c | |||
| 516 | 495 | ||
| 517 | - do { | 496 | - do { |
| 518 | - n = _Py_read(fd, buffer, (size_t)size); | 497 | - n = _Py_read(fd, buffer, (size_t)size); |
| 519 | - if (n == -1) | 498 | - if (n == -1) { |
| 520 | - return -1; | 499 | - return -1; |
| 500 | - } | ||
| 521 | - if (n == 0) { | 501 | - if (n == 0) { |
| 522 | - PyErr_Format(PyExc_RuntimeError, | 502 | - PyErr_Format(PyExc_RuntimeError, |
| 523 | - "Failed to read %zi bytes from /dev/urandom", | 503 | - "Failed to read %zi bytes from /dev/urandom", |
| @@ -566,7 +546,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 566 | return 0; | 546 | return 0; |
| 567 | } | 547 | } |
| 568 | 548 | ||
| 569 | @@ -349,8 +401,8 @@ dev_urandom_close(void) | 549 | @@ -376,8 +402,8 @@ dev_urandom_close(void) |
| 570 | urandom_cache.fd = -1; | 550 | urandom_cache.fd = -1; |
| 571 | } | 551 | } |
| 572 | } | 552 | } |
| @@ -576,7 +556,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 576 | 556 | ||
| 577 | /* Fill buffer with pseudo-random bytes generated by a linear congruent | 557 | /* Fill buffer with pseudo-random bytes generated by a linear congruent |
| 578 | generator (LCG): | 558 | generator (LCG): |
| 579 | @@ -373,29 +425,98 @@ lcg_urandom(unsigned int x0, unsigned ch | 559 | @@ -400,31 +426,100 @@ lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size) |
| 580 | } | 560 | } |
| 581 | } | 561 | } |
| 582 | 562 | ||
| @@ -661,7 +641,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 661 | #else | 641 | #else |
| 662 | - return dev_urandom_python((char*)buffer, size); | 642 | - return dev_urandom_python((char*)buffer, size); |
| 663 | + res = py_getentropy(buffer, size, raise); | 643 | + res = py_getentropy(buffer, size, raise); |
| 664 | #endif | 644 | +#endif |
| 665 | + if (res < 0) { | 645 | + if (res < 0) { |
| 666 | + return -1; | 646 | + return -1; |
| 667 | + } | 647 | + } |
| @@ -673,9 +653,9 @@ Index: Python-3.5.2/Python/random.c | |||
| 673 | +#endif | 653 | +#endif |
| 674 | + | 654 | + |
| 675 | + return dev_urandom(buffer, size, raise); | 655 | + return dev_urandom(buffer, size, raise); |
| 676 | +#endif | 656 | #endif |
| 677 | +} | 657 | } |
| 678 | + | 658 | |
| 679 | +/* Fill buffer with size pseudo-random bytes from the operating system random | 659 | +/* Fill buffer with size pseudo-random bytes from the operating system random |
| 680 | + number generator (RNG). It is suitable for most cryptographic purposes | 660 | + number generator (RNG). It is suitable for most cryptographic purposes |
| 681 | + except long living private keys for asymmetric encryption. | 661 | + except long living private keys for asymmetric encryption. |
| @@ -685,10 +665,12 @@ Index: Python-3.5.2/Python/random.c | |||
| 685 | +_PyOS_URandom(void *buffer, Py_ssize_t size) | 665 | +_PyOS_URandom(void *buffer, Py_ssize_t size) |
| 686 | +{ | 666 | +{ |
| 687 | + return pyurandom(buffer, size, 1); | 667 | + return pyurandom(buffer, size, 1); |
| 688 | } | 668 | +} |
| 689 | 669 | + | |
| 690 | void | 670 | void |
| 691 | @@ -436,13 +557,14 @@ _PyRandom_Init(void) | 671 | _PyRandom_Init(void) |
| 672 | { | ||
| 673 | @@ -463,13 +558,14 @@ _PyRandom_Init(void) | ||
| 692 | } | 674 | } |
| 693 | } | 675 | } |
| 694 | else { | 676 | else { |
| @@ -710,7 +692,7 @@ Index: Python-3.5.2/Python/random.c | |||
| 710 | } | 692 | } |
| 711 | } | 693 | } |
| 712 | 694 | ||
| 713 | @@ -454,8 +576,6 @@ _PyRandom_Fini(void) | 695 | @@ -481,8 +577,6 @@ _PyRandom_Fini(void) |
| 714 | CryptReleaseContext(hCryptProv, 0); | 696 | CryptReleaseContext(hCryptProv, 0); |
| 715 | hCryptProv = 0; | 697 | hCryptProv = 0; |
| 716 | } | 698 | } |
