Skip to content

socket.sendmsg() and socket.recvmsg_into() crash via __buffer__ re-entrancy (related to gh-143637) #143988

@tonghuaroot

Description

@tonghuaroot

Crash report

What happened?

Bug description

Similar to gh-143637, socket.sendmsg() and socket.recvmsg_into() can crash due to re-entrant mutation during argument parsing, but via the __buffer__ protocol instead of __index__.

Affected functions

Function Argument Trigger
sendmsg() arg 1 (data buffers) __buffer__
recvmsg_into() arg 1 (buffers) __buffer__

Root cause

Same as gh-143637: PySequence_Fast() returns the original list when input is already a list. During iteration, PyObject_GetBuffer() triggers __buffer__ callbacks which can clear the list, causing subsequent accesses to read invalid memory.

PoC - sendmsg() crash

import socket

seq = []

class MutBuffer:
    def __init__(self, data):
        self._data = bytes(data)
        self.tripped = False
    
    def __buffer__(self, flags):
        if not self.tripped:
            self.tripped = True
            seq.clear()
        return memoryview(self._data)

seq[:] = [MutBuffer(b'Hello'), b'World', b'Test']
left, right = socket.socketpair()
left.sendmsg(seq)  # CRASH: Exit code 139 (SIGSEGV)

PoC - recvmsg_into() crash

import socket

seq = []

class MutBuffer:
    def __init__(self, data):
        self._data = bytearray(data)
        self.tripped = False
    
    def __buffer__(self, flags):
        if not self.tripped:
            self.tripped = True
            seq.clear()
        return memoryview(self._data)

seq[:] = [MutBuffer(b'x' * 100), bytearray(100), bytearray(100)]
left, right = socket.socketpair()
left.send(b'Hello World!')
right.recvmsg_into(seq)  # CRASH: Exit code 139 (SIGSEGV)

Fix

Replace PySequence_Fast() with PySequence_Tuple() in sock_sendmsg_iovec() and sock_recvmsg_into().

I have a PR ready.

CPython versions tested on:

main branch (3.15.0a5+)

Operating system and architecture:

macOS 15.0 arm64

CPython versions tested on:

CPython main branch

Operating systems tested on:

macOS

Output from running 'python -VV' on the command line:

No response

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions