]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.12] gh-126138: Fix use-after-free in `_asyncio.Task` by evil `__getattribute__...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Sat, 2 Nov 2024 08:03:51 +0000 (09:03 +0100)
committerGitHub <noreply@github.com>
Sat, 2 Nov 2024 08:03:51 +0000 (08:03 +0000)
gh-126138: Fix use-after-free in `_asyncio.Task` by evil `__getattribute__` (GH-126305)
(cherry picked from commit f032f6ba8fec6fab35edeec0eb40cd73e9d58928)

Co-authored-by: Nico-Posada <102486290+Nico-Posada@users.noreply.github.com>
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
Misc/NEWS.d/next/Library/2024-11-01-14-31-41.gh-issue-126138.yTniOG.rst [new file with mode: 0644]
Modules/_asynciomodule.c

diff --git a/Misc/NEWS.d/next/Library/2024-11-01-14-31-41.gh-issue-126138.yTniOG.rst b/Misc/NEWS.d/next/Library/2024-11-01-14-31-41.gh-issue-126138.yTniOG.rst
new file mode 100644 (file)
index 0000000..459eebc
--- /dev/null
@@ -0,0 +1,3 @@
+Fix a use-after-free crash on :class:`asyncio.Task` objects
+whose underlying coroutine yields an object that implements
+an evil :meth:`~object.__getattribute__`. Patch by Nico Posada.
index 9bb71623ba6c7eb967c87124a742683002b64d0f..20a9d992834b0e0ea9dbb95f79e459337229fd76 100644 (file)
@@ -2994,8 +2994,17 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
         if (task->task_must_cancel) {
             PyObject *r;
             int is_true;
+
+            // Beware: An evil `__getattribute__` could
+            // prematurely delete task->task_cancel_msg before the
+            // task is cancelled, thereby causing a UAF crash.
+            //
+            // See https://github.com/python/cpython/issues/126138
+            PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
             r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
-                                             task->task_cancel_msg);
+                                          task_cancel_msg);
+            Py_DECREF(task_cancel_msg);
+
             if (r == NULL) {
                 return NULL;
             }
@@ -3087,8 +3096,17 @@ task_step_handle_result_impl(asyncio_state *state, TaskObj *task, PyObject *resu
         if (task->task_must_cancel) {
             PyObject *r;
             int is_true;
+
+            // Beware: An evil `__getattribute__` could
+            // prematurely delete task->task_cancel_msg before the
+            // task is cancelled, thereby causing a UAF crash.
+            //
+            // See https://github.com/python/cpython/issues/126138
+            PyObject *task_cancel_msg = Py_NewRef(task->task_cancel_msg);
             r = PyObject_CallMethodOneArg(result, &_Py_ID(cancel),
-                                             task->task_cancel_msg);
+                                          task_cancel_msg);
+            Py_DECREF(task_cancel_msg);
+
             if (r == NULL) {
                 return NULL;
             }