Repository navigation
gh-157364: Fix use-after-free in TextIOWrapper during reentrant detach - #157370
Conversation
|
I will need a couple more days to look at this, it seems like this is more invasive than necessary to me and makes a number of not needed for the core UAF bug report. |
|
For gh-157364 I think the bug, and solution, is actually in Buffered I/O. This PR changes Text I/O to keep one more reference, which may also be needed. The issue though is that Buffered I/O has an internal allocation which it passes as an argument to the Raw I/O That makes two pieces to fix here:
|
|
Thanks for looking into this, @cmaloney! Regarding point 1: passing mbuf->master = *info;
mbuf->master.obj = NULL;Because of this, the resulting Regarding point 2: CPython method calls via |
|
For 1: The |
|
I don't understand well how _bufferedreader_raw_read_getbuffer() works. How is it different from the current PyBuffer_FillInfo() + PyMemoryView_FromBuffer() code? |
|
The key difference is reference ownership:
We can't use standard |
|
I have been triaging some old I/O bugs and came across gh-60198 which is exactly the BufferedReader memoryview bug here. That could be pulled out as a separate smaller PR that is likely quicker to land with its own NEWS. I think this should have two news entries: one the io.TexTIOWrapper keeping a reference to I don't like adding the two new members to In the TextIO the Incref and decref living in very different functions I'm not a big fan of... I would much rather keep |
|
@vstinner @cmaloney I narrowed this PR to the TextIOWrapper fix for gh-157364. I removed the BufferedReader change and added the requested check that the wrapper is detached after |
Just a general remark: you're making many large changes on this PR. It's not easy to follow these changes. |
vstinner
left a comment
There was a problem hiding this comment.
Good: the test does crash without the fix. So it confirms that the test checks the modified C code.
$ ./python -m test -v test_io.test_textio -m test_reentrant_detach_during_read
(...)Warning -- Unraisable exception
Exception ignored while finalizing file <_io.BufferedReader>:
Traceback (most recent call last):
File "/home/vstinner/python/main/Lib/test/test_io/test_textio.py", line 1651, in readinto
wrapper.detach()
~~~~~~~~~~~~~~^^
RuntimeError: reentrant call inside <_io.BufferedReader>
Fatal Python error: Segmentation fault
<Cannot show all threads while the GIL is disabled>
Stack (most recent call first):
File "/home/vstinner/python/main/Lib/test/test_io/test_textio.py", line 1661 in test_reentrant_detach_during_read
vstinner
left a comment
There was a problem hiding this comment.
LGTM. Returning a strong reference in buffer_access_safe() sounds like a safe move. I checked that buffer_access_safe() callers do Py_DECREF() on the buffer.
./python -m test -R 3:3 test_io doesn't report leaks. But it reports negative reference count which is surprising:
$ ./python -m test -R 3:3 test_io.test_textio
(...)
test_io.test_textio leaked [-1, -1, -1] references, sum=-3 (this is fine)
$ ./python -m test -R 3:3 test_io.test_bufferedio
(...)
test_io.test_bufferedio leaked [-3, -3, -3] references, sum=-9 (this is fine)
Ah, I get the same result on the main branch. So it's not caused by this change. |
|
Thanks the updates. I enabled auto-merge, please don't touch the PR (your branch) anymore. This change is a bugfix which should be backported to 3.14 and 3.15 branches. |
|
CI failed on test_profiling which looks independent, re-running. |
|
Sorry, @ashm-dev and @vstinner, I could not cleanly backport this to Please backport manually with cherry_picker, see the devguide for more information. |
|
Sorry, @ashm-dev and @vstinner, I could not cleanly backport this to Please backport manually with cherry_picker, see the devguide for more information. |
|
Aha, more conflicts. I will backport the change to 3.14 and 3.15 once the 3.15 branch will be unblocked (next week). |
|
PR merged, thanks @ashm-dev for your fix. |
Uh oh!
There was an error while loading. Please reload this page.