Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Use-after-free inasyncio Task deallocation via re-registering task incall_exception_handler #142556

Closed
Labels
3.14bugs and security fixes3.15new features, bugs and security fixestopic-asynciotype-crashA hard crash of the interpreter, possibly with a core dump
@jackfromeast

Description

@jackfromeast

What happened?

DuringTask teardownTaskObj_dealloc() calls the finalizer (TaskObj_finalize) which invokes the loop'scall_exception_handler (user code). If that handler re-registers the sameTask (e.g. calls_asyncio._register_task(context["task"])), the runtime may add the freed task pointer into a registry whiletp_free is still running, causing a heap use-after-free when the registry later touches the pointer.

Proof of Concept:

import_asyncioclassEvilLoop:defget_debug(self):returnFalsedefcall_exception_handler(self,context):_asyncio._register_task(context["task"])asyncdefcoro():passloop=EvilLoop()task=_asyncio.Task(coro(),loop=loop)

Affected Versions:

Python VersionStatusExit Code
Python 3.9.24+ (heads/3.9:9c4638d, Oct 17 2025, 11:19:30)Exception1
Python 3.10.19+ (heads/3.10:0142619, Oct 17 2025, 11:20:05) [GCC 13.3.0]Exception1
Python 3.11.14+ (heads/3.11:88f3f5b, Oct 17 2025, 11:20:44) [GCC 13.3.0]Exception1
Python 3.12.12+ (heads/3.12:8cb2092, Oct 17 2025, 11:21:35) [GCC 13.3.0]Exception1
Python 3.13.9+ (heads/3.13:0760a57, Oct 17 2025, 11:22:25) [GCC 13.3.0]Exception1
Python 3.14.0+ (heads/3.14:889e918, Oct 17 2025, 11:23:02) [GCC 13.3.0]ASAN1
Python 3.15.0a1+ (heads/main:fbf0843, Oct 17 2025, 11:23:37) [GCC 13.3.0]ASAN1

Vulnerable Code Snippet

static voidTaskObj_dealloc(PyObject *self){    _PyObject_ResurrectStart(self);    // Unregister the task here so that even if any subclass of Task    // which doesn't end up calling TaskObj_finalize not crashes.    unregister_task((TaskObj *)self);    PyObject_CallFinalizer(self); // Call TaskObj_finalize    if (_PyObject_ResurrectEnd(self)) {        return;    }    PyTypeObject *tp = Py_TYPE(self);    PyObject_GC_UnTrack(self);    PyObject_ClearWeakRefs(self);    (void)TaskObj_clear(self);    tp->tp_free(self);    Py_DECREF(tp);}static voidTaskObj_finalize(PyObject *op){    TaskObj *task = (TaskObj*)op;    PyObject *context;    PyObject *message = NULL;    PyObject *func;    if (task->task_state != STATE_PENDING || !task->task_log_destroy_pending) {        goto done;    }    /* Save the current exception, if any. */    PyObject *exc = PyErr_GetRaisedException();    context = PyDict_New();    if (context == NULL) {        goto finally;    }    message = PyUnicode_FromString("Task was destroyed but it is pending!");    if (message == NULL) {        goto finally;    }    if (PyDict_SetItem(context, &_Py_ID(message), message) < 0 ||        PyDict_SetItem(context, &_Py_ID(task), (PyObject*)task) < 0)    {        goto finally;    }    if (task->task_source_tb != NULL) {        if (PyDict_SetItem(context, &_Py_ID(source_traceback),                              task->task_source_tb) < 0)        {            goto finally;        }    }   // Bug: In the call_exception_handler, we re-register the task so that the registry holds its pointer// While later, the tp->tp_free(self); in TaskObj_dealloc, the task will be freed and any access to the pointer will cause UAF.// When task has ended, the call_exception_handler method will be invoked.    func = PyObject_GetAttr(task->task_loop, &_Py_ID(call_exception_handler));    if (func != NULL) {        PyObject *res = PyObject_CallOneArg(func, context);        if (res == NULL) {            PyErr_FormatUnraisable("Exception ignored while calling asyncio "                                   "function %R", func);        }        else {            Py_DECREF(res);        }        Py_DECREF(func);    }finally:    Py_XDECREF(context);    Py_XDECREF(message);    /* Restore the saved exception. */    PyErr_SetRaisedException(exc);done:    FutureObj_finalize((PyObject*)task);}

Sanitizer

===================================================================1485200==ERROR:AddressSanitizer:heap-use-after-freeonaddress0x5150000657d0atpc0x62a676285a06bp0x7ffe931f2c30sp0x7ffe931f2c20WRITEofsize8at0x5150000657d0threadT0#0 0x62a676285a05 in llist_concat Include/internal/pycore_llist.h:95#1 0x62a676285a05 in PyThreadState_Clear Python/pystate.c:1687#2 0x62a676285bb1 in interpreter_clear Python/pystate.c:746#3 0x62a676286636 in _PyInterpreterState_Clear Python/pystate.c:904#4 0x62a67627cb73 in finalize_interp_clear Python/pylifecycle.c:1920#5 0x62a67627d669 in _Py_Finalize Python/pylifecycle.c:2337#6 0x62a67627d6f2 in Py_FinalizeEx Python/pylifecycle.c:2378#7 0x62a6762df847 in Py_RunMain Modules/main.c:774#8 0x62a6762dfa2e in pymain_main Modules/main.c:802#9 0x62a6762dfdb3 in Py_BytesMain Modules/main.c:826#10 0x62a675d63645 in main Programs/python.c:15#11 0x7405bae2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58#12 0x7405bae2a28a in __libc_start_main_impl ../csu/libc-start.c:360#13 0x62a675d63574 in _start (/home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-latest/targets/cpython/python+0x2dd574) (BuildId: ff3dc40ea460bd4beb2c3a72283cca525b319bf0)0x5150000657d0islocated208bytesinsideof504-byteregion [0x515000065700,0x5150000658f8)freedbythreadT0here:#0 0x7405bb2fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52#1 0x62a675f9596d in _PyMem_RawFree Objects/obmalloc.c:91#2 0x62a675f97cd9 in _PyMem_DebugRawFree Objects/obmalloc.c:2955#3 0x62a675f97d1a in _PyMem_DebugFree Objects/obmalloc.c:3100#4 0x62a675fc006c in PyObject_Free Objects/obmalloc.c:1522#5 0x62a6761fecf7 in PyObject_GC_Del Python/gc.c:2435#6 0x62a6762eef87 in TaskObj_dealloc Modules/_asynciomodule.c:3010#7 0x62a675f8c481 in _Py_Dealloc Objects/object.c:3200#8 0x62a675fdd81c in Py_DECREF Include/refcount.h:401#9 0x62a675ff5646 in type_call Objects/typeobject.c:2463#10 0x62a675ecec71 in _PyObject_MakeTpCall Objects/call.c:242#11 0x62a675ecef19 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167#12 0x62a675ecef72 in PyObject_Vectorcall Objects/call.c:327#13 0x62a676154c60 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:2920#14 0x62a676190e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121#15 0x62a676191148 in _PyEval_Vector Python/ceval.c:2001#16 0x62a6761913f8 in PyEval_EvalCode Python/ceval.c:884#17 0x62a676288507 in run_eval_code_obj Python/pythonrun.c:1365#18 0x62a676288723 in run_mod Python/pythonrun.c:1459#19 0x62a67628957a in pyrun_file Python/pythonrun.c:1293#20 0x62a67628c220 in _PyRun_SimpleFileObject Python/pythonrun.c:521#21 0x62a67628c4f6 in _PyRun_AnyFileObject Python/pythonrun.c:81#22 0x62a6762dd74d in pymain_run_file_obj Modules/main.c:410#23 0x62a6762dd9b4 in pymain_run_file Modules/main.c:429#24 0x62a6762df1b2 in pymain_run_python Modules/main.c:691#25 0x62a6762df842 in Py_RunMain Modules/main.c:772#26 0x62a6762dfa2e in pymain_main Modules/main.c:802#27 0x62a6762dfdb3 in Py_BytesMain Modules/main.c:826#28 0x62a675d63645 in main Programs/python.c:15#29 0x7405bae2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58previouslyallocatedbythreadT0here:#0 0x7405bb2fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69#1 0x62a675f96284 in _PyMem_RawMalloc Objects/obmalloc.c:63#2 0x62a675f95655 in _PyMem_DebugRawAlloc Objects/obmalloc.c:2887#3 0x62a675f956bd in _PyMem_DebugRawMalloc Objects/obmalloc.c:2920#4 0x62a675f96f3b in _PyMem_DebugMalloc Objects/obmalloc.c:3085#5 0x62a675fbff28 in PyObject_Malloc Objects/obmalloc.c:1493#6 0x62a675ff203b in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46#7 0x62a675ff203b in _PyType_AllocNoTrack Objects/typeobject.c:2504#8 0x62a675ff21c7 in PyType_GenericAlloc Objects/typeobject.c:2535#9 0x62a675fd9dd9 in PyType_GenericNew Objects/typeobject.c:2549#10 0x62a675ff5346 in type_call Objects/typeobject.c:2448#11 0x62a675ecec71 in _PyObject_MakeTpCall Objects/call.c:242#12 0x62a675ecef19 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167#13 0x62a675ecef72 in PyObject_Vectorcall Objects/call.c:327#14 0x62a676154c60 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:2920#15 0x62a676190e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121#16 0x62a676191148 in _PyEval_Vector Python/ceval.c:2001#17 0x62a6761913f8 in PyEval_EvalCode Python/ceval.c:884#18 0x62a676288507 in run_eval_code_obj Python/pythonrun.c:1365#19 0x62a676288723 in run_mod Python/pythonrun.c:1459#20 0x62a67628957a in pyrun_file Python/pythonrun.c:1293#21 0x62a67628c220 in _PyRun_SimpleFileObject Python/pythonrun.c:521#22 0x62a67628c4f6 in _PyRun_AnyFileObject Python/pythonrun.c:81#23 0x62a6762dd74d in pymain_run_file_obj Modules/main.c:410#24 0x62a6762dd9b4 in pymain_run_file Modules/main.c:429#25 0x62a6762df1b2 in pymain_run_python Modules/main.c:691#26 0x62a6762df842 in Py_RunMain Modules/main.c:772#27 0x62a6762dfa2e in pymain_main Modules/main.c:802#28 0x62a6762dfdb3 in Py_BytesMain Modules/main.c:826#29 0x62a675d63645 in main Programs/python.c:15#30 0x7405bae2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58SUMMARY:AddressSanitizer:heap-use-after-freeInclude/internal/pycore_llist.h:95inllist_concatShadowbytesaroundthebuggyaddress:0x515000065500:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd0x515000065580:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd0x515000065600:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfafa0x515000065680:fafafafafafafafafafafafafafafafa0x515000065700:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd=>0x515000065780:fdfdfdfdfdfdfdfdfdfd[fd]fdfdfdfdfd0x515000065800:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd0x515000065880:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfa0x515000065900:fafafafafafafafafafafafafafafafa0x515000065980:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfd0x515000065a00:fdfdfdfdfdfdfdfdfdfdfdfdfdfdfdfdShadowbytelegend (oneshadowbyterepresents8applicationbytes):Addressable:00Partiallyaddressable:01020304050607Heapleftredzone:faFreedheapregion:fdStackleftredzone:f1Stackmidredzone:f2Stackrightredzone:f3Stackafterreturn:f5Stackuseafterscope:f8Globalredzone:f9Globalinitorder:f6Poisonedbyuser:f7Containeroverflow:fcArraycookie:acIntraobjectredzone:bbASaninternal:feLeftallocaredzone:caRightallocaredzone:cb==1485200==ABORTING

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.14bugs and security fixes3.15new features, bugs and security fixestopic-asynciotype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions


      [8]ページ先頭

      ©2009-2025 Movatter.jp