gh-143988: Fix re-entrant mutation crashes in socket sendmsg/recvmsg_into via __buffer__#143987
Conversation
__buffer____buffer__
333ee07 to
78c18ed
Compare
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase And if you don't make the requested changes, you will be poked with soft cushions! |
78c18ed to
42ad743
Compare
|
I have made the requested changes; please review again. |
|
Thanks for making the requested changes! @picnixz: please review the changes made to this pull request. |
|
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
|
Please read the devguide:
|
720a086 to
4b592ef
Compare
…cvmsg_into via __buffer__ Fix crashes in socket.sendmsg() and socket.recvmsg_into() that could occur if buffer sequences are mutated re-entrantly during argument parsing via __buffer__ protocol callbacks. The vulnerability occurs because: 1. PySequence_Fast() returns the original list object when the input is already a list (not a copy) 2. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which may clear the list 3. Subsequent iterations access invalid memory (heap OOB read) The fix replaces PySequence_Fast() with PySequence_Tuple() which always creates a new tuple, ensuring the sequence cannot be mutated during iteration. This addresses two vulnerabilities related to pythongh-143637: - sendmsg() argument 1 (data buffers) - via __buffer__ - recvmsg_into() argument 1 (buffers) - via __buffer__
4b592ef to
2c8aad6
Compare
Sorry about the force pushes - I'll use regular commits going forward. Thanks for the reminder about the devguide. |
|
I have made the requested changes; please review again. |
|
Thanks for making the requested changes! @picnixz: please review the changes made to this pull request. |
| @@ -0,0 +1,3 @@ | |||
| Fixed crashes in :meth:`socket.socket.sendmsg` and :meth:`socket.socket.recvmsg_into` | |||
| that could occur if buffer sequences are mutated re-entrantly during argument parsing | |||
There was a problem hiding this comment.
that could occur if buffer sequences are concurrently mutated
- Remove argument parsing mention. It is an implementation detail.
- We do not really use the term re-entrency. I do not share the definition of re-entrency and prefer using concurrently here (you do two things at the same time)
@vstinner prefers the original name; revert the rename and keep the diff minimal.
…WS to Library - Rename sock_recvmsg_into's fast to buffers_tuple (per @vstinner). - Trim ReentrantMutationTests docstring to fit 80 columns. - This is a crash-robustness fix, not a security vulnerability; move the NEWS entry from Security/ to Library/.
|
Thanks @vstinner! Addressed all three:
The failing |
|
@picnixz: Would you mind to review the updated PR? It seems like 2 of your comments were not addressed yet. |
|
I think the docs issue is because of the branch not being up-to-date. You can hit the "Update branch" button to merge main into this branch (just don't force push) |
|
Thanks @tonghuaroot for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13. |
|
Thanks @tonghuaroot for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.15. |
|
Thanks @tonghuaroot for the PR, and @vstinner for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14. |
|
Sorry, @tonghuaroot and @vstinner, I could not cleanly backport this to |
|
Sorry, @tonghuaroot and @vstinner, I could not cleanly backport this to |
|
GH-151246 is a backport of this pull request to the 3.15 branch. |
…cvmsg_into (python#143987) Fix crashes in socket.sendmsg() and socket.recvmsg_into() that could occur if buffer sequences are mutated re-entrantly during argument parsing via __buffer__ protocol callbacks. The bug occurs because: 1. PySequence_Fast() returns the original list object when the input is already a list (not a copy). 2. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which may clear the list. 3. Subsequent iterations access invalid memory (heap OOB read). The fix replaces PySequence_Fast() with PySequence_Tuple() which always creates a new tuple, ensuring the sequence cannot be mutated during iteration. Co-authored-by: tonghuaroot <23011166+tonghuaroot@users.noreply.github.com> (cherry picked from commit 896f7fd)
|
GH-151251 is a backport of this pull request to the 3.14 branch. |
|
Merged, thanks for your fix. I backport the change to 3.14 and 3.15 branches. (The 3.14 backport will be backported to 3.13 once it will be merged.) |
…ecvmsg_into (#143987) (#151251) gh-143988: Fix re-entrant mutation crashes in socket sendmsg/recvmsg_into (#143987) Fix crashes in socket.sendmsg() and socket.recvmsg_into() that could occur if buffer sequences are mutated re-entrantly during argument parsing via __buffer__ protocol callbacks. The bug occurs because: 1. PySequence_Fast() returns the original list object when the input is already a list (not a copy). 2. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which may clear the list. 3. Subsequent iterations access invalid memory (heap OOB read). The fix replaces PySequence_Fast() with PySequence_Tuple() which always creates a new tuple, ensuring the sequence cannot be mutated during iteration. (cherry picked from commit 896f7fd) Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com> Co-authored-by: tonghuaroot <23011166+tonghuaroot@users.noreply.github.com>
…ecvmsg_into (GH-143987) (#151246) gh-143988: Fix re-entrant mutation crashes in socket sendmsg/recvmsg_into (GH-143987) Fix crashes in socket.sendmsg() and socket.recvmsg_into() that could occur if buffer sequences are mutated re-entrantly during argument parsing via __buffer__ protocol callbacks. The bug occurs because: 1. PySequence_Fast() returns the original list object when the input is already a list (not a copy). 2. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which may clear the list. 3. Subsequent iterations access invalid memory (heap OOB read). The fix replaces PySequence_Fast() with PySequence_Tuple() which always creates a new tuple, ensuring the sequence cannot be mutated during iteration. (cherry picked from commit 896f7fd) Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com> Co-authored-by: tonghuaroot <23011166+tonghuaroot@users.noreply.github.com>
…dmsg/recvmsg_into (#143987) (#151251) (#151256) [3.14] gh-143988: Fix re-entrant mutation crashes in socket sendmsg/recvmsg_into (#143987) (#151251) gh-143988: Fix re-entrant mutation crashes in socket sendmsg/recvmsg_into (#143987) Fix crashes in socket.sendmsg() and socket.recvmsg_into() that could occur if buffer sequences are mutated re-entrantly during argument parsing via __buffer__ protocol callbacks. The bug occurs because: 1. PySequence_Fast() returns the original list object when the input is already a list (not a copy). 2. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which may clear the list. 3. Subsequent iterations access invalid memory (heap OOB read). The fix replaces PySequence_Fast() with PySequence_Tuple() which always creates a new tuple, ensuring the sequence cannot be mutated during iteration. (cherry picked from commit 896f7fd) (cherry picked from commit 632daaf) Co-authored-by: tonghuaroot (童话) <tonghuaroot@gmail.com> Co-authored-by: tonghuaroot <23011166+tonghuaroot@users.noreply.github.com>
Summary
This PR fixes two heap out-of-bounds read vulnerabilities in
socket.sendmsg()andsocket.recvmsg_into()that are related to gh-143637.While gh-143637 addresses the
__index__re-entrancy issue insendmsg()ancillary data parsing (argument 2), there are two additional vulnerable code paths that use the__buffer__protocol:socket.sendmsg()argument 1 (data buffers) - insock_sendmsg_iovec()socket.recvmsg_into()argument 1 (buffers) - insock_recvmsg_into()Root Cause
The vulnerability occurs because:
PySequence_Fast()returns the original list object when the input is already a list (not a copy)PyObject_GetBuffer()triggers__buffer__protocol callbacks which may clear the listProof of Concept
sendmsg()data buffers crash:recvmsg_into()buffers crash:Fix
Replace
PySequence_Fast()withPySequence_Tuple()which always creates a new tuple, ensuring the sequence cannot be mutated during iteration.Testing
Added
Lib/test/test_socket_reentrant.pywith regression tests for both vulnerable code paths.Note: This is related to but separate from PR #143892 which fixes the
__index__issue.