summaryrefslogtreecommitdiff
path: root/meta-openembedded/meta-python
diff options
context:
space:
mode:
Diffstat (limited to 'meta-openembedded/meta-python')
-rw-r--r--meta-openembedded/meta-python/recipes-devtools/python/python3-django_4.2.1.bb (renamed from meta-openembedded/meta-python/recipes-devtools/python/python3-django_4.0.2.bb)2
-rw-r--r--meta-openembedded/meta-python/recipes-devtools/python/python3-gcovr_5.1.bb2
-rw-r--r--meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto/CVE-2020-25657.patch175
-rw-r--r--meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto_0.38.0.bb1
-rw-r--r--meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2023-25577.patch231
-rw-r--r--meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb2
6 files changed, 411 insertions, 2 deletions
diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-django_4.0.2.bb b/meta-openembedded/meta-python/recipes-devtools/python/python3-django_4.2.1.bb
index 690b9809dc..4daca65eb5 100644
--- a/meta-openembedded/meta-python/recipes-devtools/python/python3-django_4.0.2.bb
+++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-django_4.2.1.bb
@@ -1,7 +1,7 @@
require python-django.inc
inherit setuptools3
-SRC_URI[sha256sum] = "110fb58fb12eca59e072ad59fc42d771cd642dd7a2f2416582aa9da7a8ef954a"
+SRC_URI[sha256sum] = "7efa6b1f781a6119a10ac94b4794ded90db8accbe7802281cd26f8664ffed59c"
RDEPENDS:${PN} += "\
${PYTHON_PN}-sqlparse \
diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-gcovr_5.1.bb b/meta-openembedded/meta-python/recipes-devtools/python/python3-gcovr_5.1.bb
index 995f3b779b..1c4279fd1e 100644
--- a/meta-openembedded/meta-python/recipes-devtools/python/python3-gcovr_5.1.bb
+++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-gcovr_5.1.bb
@@ -12,6 +12,6 @@ S = "${WORKDIR}/git"
inherit setuptools3
PIP_INSTALL_PACKAGE = "gcovr"
-RDEPENDS:${PN} += "${PYTHON_PN}-jinja2 ${PYTHON_PN}-lxml ${PYTHON_PN}-setuptools ${PYTHON_PN}-pygments"
+RDEPENDS:${PN} += "${PYTHON_PN}-jinja2 ${PYTHON_PN}-lxml ${PYTHON_PN}-setuptools ${PYTHON_PN}-pygments ${PYTHON_PN}-multiprocessing"
BBCLASSEXTEND = "native nativesdk"
diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto/CVE-2020-25657.patch b/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto/CVE-2020-25657.patch
new file mode 100644
index 0000000000..cc915f1478
--- /dev/null
+++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto/CVE-2020-25657.patch
@@ -0,0 +1,175 @@
+From 2fa92e048b76fcc7bf2d4f4443478c8292d17470 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Mat=C4=9Bj=20Cepl?= <mcepl@cepl.eu>
+Date: Thu, 1 Jun 2023 14:56:34 +0000
+Subject: [PATCH] Mitigate the Bleichenbacher timing attacks in the RSA
+ decryption API (CVE-2020-25657)
+
+Fixes #282
+
+CVE: CVE-2020-25657
+
+Upstream-Status: Backport [https://gitlab.com/m2crypto/m2crypto/-/commit/84c53958def0f510e92119fca14d74f94215827a]
+
+Signed-off-by: Narpat Mali <narpat.mali@windriver.com>
+---
+ src/SWIG/_m2crypto_wrap.c | 20 ++++++++++++--------
+ src/SWIG/_rsa.i | 20 ++++++++++++--------
+ tests/test_rsa.py | 15 +++++++--------
+ 3 files changed, 31 insertions(+), 24 deletions(-)
+
+diff --git a/src/SWIG/_m2crypto_wrap.c b/src/SWIG/_m2crypto_wrap.c
+index 3db88b9..6aafe1f 100644
+--- a/src/SWIG/_m2crypto_wrap.c
++++ b/src/SWIG/_m2crypto_wrap.c
+@@ -7129,9 +7129,10 @@ PyObject *rsa_private_encrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_private_encrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+@@ -7159,9 +7160,10 @@ PyObject *rsa_public_decrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_public_decrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+@@ -7186,9 +7188,10 @@ PyObject *rsa_public_encrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_public_encrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+@@ -7213,9 +7216,10 @@ PyObject *rsa_private_decrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_private_decrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+
+diff --git a/src/SWIG/_rsa.i b/src/SWIG/_rsa.i
+index bc714e0..1377b8b 100644
+--- a/src/SWIG/_rsa.i
++++ b/src/SWIG/_rsa.i
+@@ -239,9 +239,10 @@ PyObject *rsa_private_encrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_private_encrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+@@ -269,9 +270,10 @@ PyObject *rsa_public_decrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_public_decrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+@@ -296,9 +298,10 @@ PyObject *rsa_public_encrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_public_encrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+@@ -323,9 +326,10 @@ PyObject *rsa_private_decrypt(RSA *rsa, PyObject *from, int padding) {
+ tlen = RSA_private_decrypt(flen, (unsigned char *)fbuf,
+ (unsigned char *)tbuf, rsa, padding);
+ if (tlen == -1) {
+- m2_PyErr_Msg(_rsa_err);
++ ERR_clear_error();
++ PyErr_Clear();
+ PyMem_Free(tbuf);
+- return NULL;
++ Py_RETURN_NONE;
+ }
+ ret = PyBytes_FromStringAndSize((const char *)tbuf, tlen);
+
+diff --git a/tests/test_rsa.py b/tests/test_rsa.py
+index 7bb3af7..5e75d68 100644
+--- a/tests/test_rsa.py
++++ b/tests/test_rsa.py
+@@ -109,8 +109,9 @@ class RSATestCase(unittest.TestCase):
+ # The other paddings.
+ for padding in self.s_padding_nok:
+ p = getattr(RSA, padding)
+- with self.assertRaises(RSA.RSAError):
+- priv.private_encrypt(self.data, p)
++ # Exception disabled as a part of mitigation against CVE-2020-25657
++ # with self.assertRaises(RSA.RSAError):
++ priv.private_encrypt(self.data, p)
+ # Type-check the data to be encrypted.
+ with self.assertRaises(TypeError):
+ priv.private_encrypt(self.gen_callback, RSA.pkcs1_padding)
+@@ -127,10 +128,12 @@ class RSATestCase(unittest.TestCase):
+ self.assertEqual(ptxt, self.data)
+
+ # no_padding
+- with six.assertRaisesRegex(self, RSA.RSAError, 'data too small'):
+- priv.public_encrypt(self.data, RSA.no_padding)
++ # Exception disabled as a part of mitigation against CVE-2020-25657
++ # with six.assertRaisesRegex(self, RSA.RSAError, 'data too small'):
++ priv.public_encrypt(self.data, RSA.no_padding)
+
+ # Type-check the data to be encrypted.
++ # Exception disabled as a part of mitigation against CVE-2020-25657
+ with self.assertRaises(TypeError):
+ priv.public_encrypt(self.gen_callback, RSA.pkcs1_padding)
+
+@@ -146,10 +149,6 @@ class RSATestCase(unittest.TestCase):
+ b'\000\000\000\003\001\000\001') # aka 65537 aka 0xf4
+ with self.assertRaises(RSA.RSAError):
+ setattr(rsa, 'e', '\000\000\000\003\001\000\001')
+- with self.assertRaises(RSA.RSAError):
+- rsa.private_encrypt(1)
+- with self.assertRaises(RSA.RSAError):
+- rsa.private_decrypt(1)
+ assert rsa.check_key()
+
+ def test_loadpub_bad(self):
+--
+2.40.0
diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto_0.38.0.bb b/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto_0.38.0.bb
index 51a0dd676e..155a9066ca 100644
--- a/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto_0.38.0.bb
+++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-m2crypto_0.38.0.bb
@@ -10,6 +10,7 @@ SRC_URI += "file://0001-setup.py-link-in-sysroot-not-in-host-directories.patch \
file://cross-compile-platform.patch \
file://avoid-host-contamination.patch \
file://0001-setup.py-address-openssl-3.x-build-issue.patch \
+ file://CVE-2020-25657.patch \
"
SRC_URI[sha256sum] = "99f2260a30901c949a8dc6d5f82cd5312ffb8abc92e76633baf231bbbcb2decb"
diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2023-25577.patch b/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2023-25577.patch
new file mode 100644
index 0000000000..61551d8fca
--- /dev/null
+++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug/CVE-2023-25577.patch
@@ -0,0 +1,231 @@
+From 5a56cdcbaec2153cd67596c6c2c8056e1ea5ed56 Mon Sep 17 00:00:00 2001
+From: David Lord <davidism@gmail.com>
+Date: Tue, 2 May 2023 11:31:10 +0000
+Subject: [PATCH] Merge pull request from GHSA-xg9f-g7g7-2323
+
+limit the maximum number of multipart form parts
+
+CVE: CVE-2023-25577
+
+Upstream-Status: Backport [https://github.com/pallets/werkzeug/commit/517cac5a804e8c4dc4ed038bb20dacd038e7a9f1]
+
+Signed-off-by: Narpat Mali <narpat.mali@windriver.com>
+---
+ CHANGES.rst | 5 +++++
+ docs/request_data.rst | 37 +++++++++++++++++---------------
+ src/werkzeug/formparser.py | 12 ++++++++++-
+ src/werkzeug/sansio/multipart.py | 8 +++++++
+ src/werkzeug/wrappers/request.py | 8 +++++++
+ tests/test_formparser.py | 9 ++++++++
+ 6 files changed, 61 insertions(+), 18 deletions(-)
+
+diff --git a/CHANGES.rst b/CHANGES.rst
+index a351d7c..6e809ba 100644
+--- a/CHANGES.rst
++++ b/CHANGES.rst
+@@ -1,5 +1,10 @@
+ .. currentmodule:: werkzeug
+
++- Specify a maximum number of multipart parts, default 1000, after which a
++ ``RequestEntityTooLarge`` exception is raised on parsing. This mitigates a DoS
++ attack where a larger number of form/file parts would result in disproportionate
++ resource use.
++
+ Version 2.1.1
+ -------------
+
+diff --git a/docs/request_data.rst b/docs/request_data.rst
+index 83c6278..e55841e 100644
+--- a/docs/request_data.rst
++++ b/docs/request_data.rst
+@@ -73,23 +73,26 @@ read the stream *or* call :meth:`~Request.get_data`.
+ Limiting Request Data
+ ---------------------
+
+-To avoid being the victim of a DDOS attack you can set the maximum
+-accepted content length and request field sizes. The :class:`Request`
+-class has two attributes for that: :attr:`~Request.max_content_length`
+-and :attr:`~Request.max_form_memory_size`.
+-
+-The first one can be used to limit the total content length. For example
+-by setting it to ``1024 * 1024 * 16`` the request won't accept more than
+-16MB of transmitted data.
+-
+-Because certain data can't be moved to the hard disk (regular post data)
+-whereas temporary files can, there is a second limit you can set. The
+-:attr:`~Request.max_form_memory_size` limits the size of `POST`
+-transmitted form data. By setting it to ``1024 * 1024 * 2`` you can make
+-sure that all in memory-stored fields are not more than 2MB in size.
+-
+-This however does *not* affect in-memory stored files if the
+-`stream_factory` used returns a in-memory file.
++The :class:`Request` class provides a few attributes to control how much data is
++processed from the request body. This can help mitigate DoS attacks that craft the
++request in such a way that the server uses too many resources to handle it. Each of
++these limits will raise a :exc:`~werkzeug.exceptions.RequestEntityTooLarge` if they are
++exceeded.
++
++- :attr:`~Request.max_content_length` Stop reading request data after this number
++ of bytes. It's better to configure this in the WSGI server or HTTP server, rather
++ than the WSGI application.
++- :attr:`~Request.max_form_memory_size` Stop reading request data if any form part is
++ larger than this number of bytes. While file parts can be moved to disk, regular
++ form field data is stored in memory only.
++- :attr:`~Request.max_form_parts` Stop reading request data if more than this number
++ of parts are sent in multipart form data. This is useful to stop a very large number
++ of very small parts, especially file parts. The default is 1000.
++
++Using Werkzeug to set these limits is only one layer of protection. WSGI servers
++and HTTPS servers should set their own limits on size and timeouts. The operating system
++or container manager should set limits on memory and processing time for server
++processes.
+
+
+ How to extend Parsing?
+diff --git a/src/werkzeug/formparser.py b/src/werkzeug/formparser.py
+index 10d58ca..bebb2fc 100644
+--- a/src/werkzeug/formparser.py
++++ b/src/werkzeug/formparser.py
+@@ -179,6 +179,8 @@ class FormDataParser:
+ :param cls: an optional dict class to use. If this is not specified
+ or `None` the default :class:`MultiDict` is used.
+ :param silent: If set to False parsing errors will not be caught.
++ :param max_form_parts: The maximum number of parts to be parsed. If this is
++ exceeded, a :exc:`~exceptions.RequestEntityTooLarge` exception is raised.
+ """
+
+ def __init__(
+@@ -190,6 +192,8 @@ class FormDataParser:
+ max_content_length: t.Optional[int] = None,
+ cls: t.Optional[t.Type[MultiDict]] = None,
+ silent: bool = True,
++ *,
++ max_form_parts: t.Optional[int] = None,
+ ) -> None:
+ if stream_factory is None:
+ stream_factory = default_stream_factory
+@@ -199,6 +203,7 @@ class FormDataParser:
+ self.errors = errors
+ self.max_form_memory_size = max_form_memory_size
+ self.max_content_length = max_content_length
++ self.max_form_parts = max_form_parts
+
+ if cls is None:
+ cls = MultiDict
+@@ -281,6 +286,7 @@ class FormDataParser:
+ self.errors,
+ max_form_memory_size=self.max_form_memory_size,
+ cls=self.cls,
++ max_form_parts=self.max_form_parts,
+ )
+ boundary = options.get("boundary", "").encode("ascii")
+
+@@ -346,10 +352,12 @@ class MultiPartParser:
+ max_form_memory_size: t.Optional[int] = None,
+ cls: t.Optional[t.Type[MultiDict]] = None,
+ buffer_size: int = 64 * 1024,
++ max_form_parts: t.Optional[int] = None,
+ ) -> None:
+ self.charset = charset
+ self.errors = errors
+ self.max_form_memory_size = max_form_memory_size
++ self.max_form_parts = max_form_parts
+
+ if stream_factory is None:
+ stream_factory = default_stream_factory
+@@ -409,7 +417,9 @@ class MultiPartParser:
+ [None],
+ )
+
+- parser = MultipartDecoder(boundary, self.max_form_memory_size)
++ parser = MultipartDecoder(
++ boundary, self.max_form_memory_size, max_parts=self.max_form_parts
++ )
+
+ fields = []
+ files = []
+diff --git a/src/werkzeug/sansio/multipart.py b/src/werkzeug/sansio/multipart.py
+index 2d54422..e7d742b 100644
+--- a/src/werkzeug/sansio/multipart.py
++++ b/src/werkzeug/sansio/multipart.py
+@@ -83,10 +83,13 @@ class MultipartDecoder:
+ self,
+ boundary: bytes,
+ max_form_memory_size: Optional[int] = None,
++ *,
++ max_parts: Optional[int] = None,
+ ) -> None:
+ self.buffer = bytearray()
+ self.complete = False
+ self.max_form_memory_size = max_form_memory_size
++ self.max_parts = max_parts
+ self.state = State.PREAMBLE
+ self.boundary = boundary
+
+@@ -113,6 +116,7 @@ class MultipartDecoder:
+ % (LINE_BREAK, re.escape(boundary), LINE_BREAK, LINE_BREAK),
+ re.MULTILINE,
+ )
++ self._parts_decoded = 0
+
+ def last_newline(self) -> int:
+ try:
+@@ -177,6 +181,10 @@ class MultipartDecoder:
+ name=name,
+ )
+ self.state = State.DATA
++ self._parts_decoded += 1
++
++ if self.max_parts is not None and self._parts_decoded > self.max_parts:
++ raise RequestEntityTooLarge()
+
+ elif self.state == State.DATA:
+ if self.buffer.find(b"--" + self.boundary) == -1:
+diff --git a/src/werkzeug/wrappers/request.py b/src/werkzeug/wrappers/request.py
+index 57b739c..a6d5429 100644
+--- a/src/werkzeug/wrappers/request.py
++++ b/src/werkzeug/wrappers/request.py
+@@ -83,6 +83,13 @@ class Request(_SansIORequest):
+ #: .. versionadded:: 0.5
+ max_form_memory_size: t.Optional[int] = None
+
++ #: The maximum number of multipart parts to parse, passed to
++ #: :attr:`form_data_parser_class`. Parsing form data with more than this
++ #: many parts will raise :exc:`~.RequestEntityTooLarge`.
++ #:
++ #: .. versionadded:: 2.2.3
++ max_form_parts = 1000
++
+ #: The form data parser that should be used. Can be replaced to customize
+ #: the form date parsing.
+ form_data_parser_class: t.Type[FormDataParser] = FormDataParser
+@@ -246,6 +253,7 @@ class Request(_SansIORequest):
+ self.max_form_memory_size,
+ self.max_content_length,
+ self.parameter_storage_class,
++ max_form_parts=self.max_form_parts,
+ )
+
+ def _load_form_data(self) -> None:
+diff --git a/tests/test_formparser.py b/tests/test_formparser.py
+index 5fc803e..834324f 100644
+--- a/tests/test_formparser.py
++++ b/tests/test_formparser.py
+@@ -127,6 +127,15 @@ class TestFormParser:
+ req.max_form_memory_size = 400
+ assert req.form["foo"] == "Hello World"
+
++ req = Request.from_values(
++ input_stream=io.BytesIO(data),
++ content_length=len(data),
++ content_type="multipart/form-data; boundary=foo",
++ method="POST",
++ )
++ req.max_form_parts = 1
++ pytest.raises(RequestEntityTooLarge, lambda: req.form["foo"])
++
+ def test_missing_multipart_boundary(self):
+ data = (
+ b"--foo\r\nContent-Disposition: form-field; name=foo\r\n\r\n"
+--
+2.40.0
diff --git a/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb b/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb
index 476a3a5964..324a4b7996 100644
--- a/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb
+++ b/meta-openembedded/meta-python/recipes-devtools/python/python3-werkzeug_2.1.1.bb
@@ -12,6 +12,8 @@ LIC_FILES_CHKSUM = "file://LICENSE.rst;md5=5dc88300786f1c214c1e9827a5229462"
PYPI_PACKAGE = "Werkzeug"
+SRC_URI += "file://CVE-2023-25577.patch"
+
SRC_URI[sha256sum] = "f8e89a20aeabbe8a893c24a461d3ee5dad2123b05cc6abd73ceed01d39c3ae74"
inherit pypi setuptools3