summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNico-Posada <102486290+Nico-Posada@users.noreply.github.com>2024-11-02 07:46:00 (GMT)
committerGitHub <noreply@github.com>2024-11-02 07:46:00 (GMT)
commitf032f6ba8fec6fab35edeec0eb40cd73e9d58928 (patch)
tree36195cbe7b3e64d591688a3593290b70cff8477b
parent914356f4d485e378eb692e57d822b893acc0c0da (diff)
downloadcpython-f032f6ba8fec6fab35edeec0eb40cd73e9d58928.zip
cpython-f032f6ba8fec6fab35edeec0eb40cd73e9d58928.tar.gz
cpython-f032f6ba8fec6fab35edeec0eb40cd73e9d58928.tar.bz2
gh-126138: Fix use-after-free in `_asyncio.Task` by evil `__getattribute__` (#126305)
Co-authored-by: Carol Willing <carolcode@willingconsulting.com>
-rw-r--r--Misc/NEWS.d/next/Library/2024-11-01-14-31-41.gh-issue-126138.yTniOG.rst3
-rw-r--r--Modules/_asynciomodule.c22
2 files changed, 23 insertions, 2 deletions
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
index 0000000..459eebc
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-11-01-14-31-41.gh-issue-126138.yTniOG.rst
@@ -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.
diff --git a/Modules/_asynciomodule.c b/Modules/_asynciomodule.c
index 7483e9c..214c18e 100644
--- a/Modules/_asynciomodule.c
+++ b/Modules/_asynciomodule.c
@@ -2967,8 +2967,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;
}
@@ -3060,8 +3069,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;
}