New submission from Bar Harel <bzvi7...@gmail.com>:

Hey guys,

I found a pretty dangerous bug that allows acquiring locks in asyncio without 
them being free.

This happens due to double release (calling _wake_up_first) from both release 
and acquire in case of cancellation.

The example I've uploaded exploits it by acquiring 4 times, which grooms the 
loop's _ready queue, cancelling the second acquire to add the cancellation to 
the _ready queue, and releasing once to add the next waiter (number 3) to the 
_ready queue. Next event loop step causes the cancellation to run first, 
skipping the queued waiter (due to .done check being true) and waking the next 
waiter in line (number 4). Then both number 3 and number 4 run together on the 
same Lock.

I'm not at home so it's hard for me to code but the simple way of fixing it is 
by adding this line - "if self._locked: yield from self.acquire()" after the 
"yield from fut" (quite minimal overhead and only if bug happens, so no harm) 
or by slightly restructuring the code and the checks regarding cancelled 
futures.

I can later on post the restructured code but I think the simple if statement 
is a pretty fine and efficient fix.

----------
components: asyncio
files: bug.py
messages: 311361
nosy: asvetlov, bar.harel, yselivanov
priority: normal
severity: normal
status: open
title: Asyncio Lock safety issue (unlimited acquire)
type: security
versions: Python 3.4, Python 3.5, Python 3.6, Python 3.7, Python 3.8
Added file: https://bugs.python.org/file47419/bug.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue32734>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to