Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork33.7k
Closed
Description
Crash report
What happened?
This is the bug I mentioned I was looking into in#126080 (comment), but it's the same as all the ones that came before this.
cpython/Modules/_asynciomodule.c
Lines 3057 to 3060 in9effa0f
| PyObject*r; | |
| intis_true; | |
| r=PyObject_CallMethodOneArg(result,&_Py_ID(cancel), | |
| task->task_cancel_msg); |
task->task_cancel_msg is missing an incref before usage so we can use a malicious__getattribute__ function in our class to free it before it gets sent to ourcancel function.
PoC
importasyncioimporttypesasyncdefevil_coroutine():@types.coroutinedefsync_generator():# ensure to keep obj alive after the first send() callglobalevilwhile1:yieldevilawaitsync_generator()classLoop:is_running=staticmethod(lambda:True)get_debug=staticmethod(lambda:False)classEvil:_asyncio_future_blocking=Trueget_loop=staticmethod(lambda:normal_loop)defadd_done_callback(self,callback,*args,**kwargs):# sets task_cancel_msg to our victim object which will be deletedasyncio.Task.cancel(task,to_uaf)defcancel(self,msg):# if hasn't crashed at this point, you'll see its the same object that was just deletedprint("in cancel",hex(id(msg)))def__getattribute__(self,name):globalto_uafifname=="cancel":classBreak:def__str__(self):raiseRuntimeError("break")# at this point, our obj to uaf only has 2 refs, `to_uaf` and `task->task_cancel_msg`. Doing a partial task init will clear# fut->fut_cancel_msg (same thing as task_cancel_msg, it's just been cast to a fut obj), and then we can just `del to_uaf` to free# the object before it gets sent to our `cancel` functry:task.__init__(coro,loop=normal_loop,name=Break())exceptExceptionase:asserttype(e)==RuntimeErrorande.args[0]=="break"delto_uaf# to_uaf has now been deleted, but it will still be sent to our `cancel` funcreturnobject.__getattribute__(self,name)classDelTracker:def__del__(self):print("deleting",hex(id(self)))to_uaf=DelTracker()normal_loop=Loop()coro=evil_coroutine()evil=Evil()task=asyncio.Task.__new__(asyncio.Task)task.__init__(coro,loop=normal_loop,name="init",eager_start=True)
Output
deleting 0x7f7a49cf9940in cancel 0x7f7a49cf9940Segmentation faultCPython versions tested on:
3.13
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.13.0 (tags/v3.13.0:60403a5409f, Oct 10 2024, 09:24:12) [GCC 13.2.0]
Linked PRs
Metadata
Metadata
Assignees
Labels
Projects
Status
Done