Skip to content

Heap out-of-bound read in socket.sendmsg ancillary parser after re-entrant __index__ clears the control list #143637

Closed

Description

@jackfromeast

What happened?

_socket_socket_sendmsg_impl fast-paths ancillary data with PySequence_Fast, assuming the original list stays stable. Parsing each (level, type, data) tuple calls PyLong_AsLongAndOverflow, which runs __index__; a malicious __index__ can clear the shared list mid-loop, leaving ncmsgs and cached element pointers stale. The next PySequence_Fast_GET_ITEM then indexes past the shortened list and dereferences freed slots, crashing with a heap OOB read at Modules/socketmodule.c:5005.

Proof of Concept:

import socket

seq = []

class Mut:
    def __init__(self):
        self.tripped = False
    def __index__(self):
        if not self.tripped:
            self.tripped = True
            seq.clear()
        return 0

seq[:] = [
    (socket.SOL_SOCKET, Mut(), b'x'),
    (socket.SOL_SOCKET, 0, b'x'),
]
left, right = socket.socketpair()
left.sendmsg([b'x'], seq)

Vulnerable Code Snippet:

Click to expand
/* Buggy Re-entrant Path */
long
PyLong_AsLongAndOverflow(PyObject *vv, int *overflow)
{
    /* ... */
    if (PyLong_Check(vv)) {
        v = (PyLongObject *)vv;
    }
    else {
        v = (PyLongObject *)_PyNumber_Index(vv);  /* Reentrant call site */
        if (v == NULL)
            return -1;
        do_decref = 1;
    }
    /* ... */
}

if ((cmsg_fast = PySequence_Fast(cmsg_arg,
                                 "sendmsg() argument 2 must be an "
                                 "iterable")) == NULL)
    goto finally;
ncmsgs = PySequence_Fast_GET_SIZE(cmsg_fast);
/* ... */
while (ncmsgbufs < ncmsgs) {
    if (!PyArg_Parse(PySequence_Fast_GET_ITEM(cmsg_fast, ncmsgbufs),  /* crashing pointer derived */
                     "(iiy*):[sendmsg() ancillary data items]",
                     &cmsgs[ncmsgbufs].level,
                     &cmsgs[ncmsgbufs].type,
                     &cmsgs[ncmsgbufs].data))  /* Crash site */
        goto finally;
    /* ... */
}

/* Clobbering Path */
static void
list_clear_impl(PyListObject *a, bool is_resize)
{
    PyObject **items = a->ob_item;
    /* ... */

    Py_ssize_t i = Py_SIZE(a);
    Py_SET_SIZE(a, 0);
    FT_ATOMIC_STORE_PTR_RELEASE(a->ob_item, NULL);
    a->allocated = 0;
    while (--i >= 0) {
        Py_XDECREF(items[i]);  /* state mutate site */
    }
    free_list_items(items, use_qsbr);
}

Sanitizer Output:

Click to expand
AddressSanitizer:DEADLYSIGNAL
=================================================================
==423360==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x73089bf5b108 bp 0x7ffe70547070 sp 0x7ffe70546db0 T0)
==423360==The signal is caused by a READ memory access.
==423360==Hint: address points to the zero page.
    #0 0x73089bf5b108 in _socket_socket_sendmsg_impl Modules/socketmodule.c:5005
    #1 0x73089bf5b108 in _socket_socket_sendmsg Modules/clinic/socketmodule.c.h:188
    #2 0x605448f333e7 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169
    #3 0x605448f333e7 in PyObject_Vectorcall Objects/call.c:327
    #4 0x605448de75a2 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620
    #5 0x6054492b1ad6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121
    #6 0x6054492b1ad6 in _PyEval_Vector Python/ceval.c:2001
    #7 0x6054492b1ad6 in PyEval_EvalCode Python/ceval.c:884
    #8 0x6054493f716e in run_eval_code_obj Python/pythonrun.c:1365
    #9 0x6054493f716e in run_mod Python/pythonrun.c:1459
    #10 0x6054493fbe17 in pyrun_file Python/pythonrun.c:1293
    #11 0x6054493fbe17 in _PyRun_SimpleFileObject Python/pythonrun.c:521
    #12 0x6054493fc93c in _PyRun_AnyFileObject Python/pythonrun.c:81
    #13 0x60544946fe3c in pymain_run_file_obj Modules/main.c:410
    #14 0x60544946fe3c in pymain_run_file Modules/main.c:429
    #15 0x60544946fe3c in pymain_run_python Modules/main.c:691
    #16 0x60544947171e in Py_RunMain Modules/main.c:772
    #17 0x60544947171e in pymain_main Modules/main.c:802
    #18 0x60544947171e in Py_BytesMain Modules/main.c:826
    #19 0x73089c42a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58
    #20 0x73089c42a28a in __libc_start_main_impl ../csu/libc-start.c:360
    #21 0x605448e0b634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV Modules/socketmodule.c:5005 in _socket_socket_sendmsg_impl
==423360==ABORTING

CPython versions tested on:

Details
Python Version Status Exit Code
Python 3.9.24+ (heads/3.9:111bbc15b26, Oct 28 2025, 16:51:20) ASAN 1
Python 3.10.19+ (heads/3.10:014261980b1, Oct 28 2025, 16:52:08) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.11.14+ (heads/3.11:88f3f5b5f11, Oct 28 2025, 16:53:08) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.12.12+ (heads/3.12:8cb2092bd8c, Oct 28 2025, 16:54:14) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.13.9+ (heads/3.13:9c8eade20c6, Oct 28 2025, 16:55:18) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.14.0+ (heads/3.14:2e216728038, Oct 28 2025, 16:56:16) [Clang 18.1.3 (1ubuntu1)] ASAN 1
Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 28 2025, 19:29:54) [GCC 13.3.0] ASAN 1

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

Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 28 2025, 19:29:54) [GCC 13.3.0]

Linked PRs

Activity

  1. added
    type-crashA hard crash of the interpreter, possibly with a core dump
    on Jan 10, 2026
  2. priyanshu2282-cyber commented on Jan 11, 2026

    @priyanshu2282-cyber
    Contributor

    Hi, thanks for the detailed report, I just wanted to ask, whether someone is working on a fix for it, or if it is okay for me to raise a PR. I would be happy to coordinate or help in any way that’s useful.

  3. added a commit that references this issue on Jan 15, 2026
  4. added 6 commits that reference this issue on Jan 18, 2026
  5. added a commit that references this issue on Feb 13, 2026
  6. added 2 commits that reference this issue on Feb 13, 2026
  7. vstinner commented on Feb 13, 2026

    @vstinner
    Member

    Fixed. Thanks for your bug report @jackfromeast.

  8. 3 remaining items

  9. vstinner commented on Feb 16, 2026

    @vstinner
    Member

    Hi @kulikjak, if I modify the unit test on Linux to raise the exception, I get the following error:

    Traceback (most recent call last):
      File "/home/vstinner/python/main/Lib/test/test_socket.py", line 2241, in test_sendmsg_reentrant_ancillary_mutation
        left.sendmsg([b'x'], seq)
        ~~~~~~~~~~~~^^^^^^^^^^^^^
    OSError: [Errno 22] Invalid argument
    

    The ancillary data is:

    (1, 0, "x")
    (1, 0, "x")
    
  10. vstinner commented on Feb 16, 2026

    @vstinner
    Member

    We can modify the test to use ancillary data which fail on all platforms.

  11. kulikjak commented on Feb 16, 2026

    @kulikjak
    Contributor

    Well, seems like Solaris is much more forgiving in how it handles invalid ancillary data. I did manage to raise an OSError with

    (socket.SOL_SOCKET, 0x1010, b'xxxx')

    0x1010 being socket.SCM_RIGHTS. Maybe we can add this line to the list?

  12. added a commit that references this issue on Feb 16, 2026
  13. vstinner commented on Feb 16, 2026

    @vstinner
    Member

    I did manage to raise an OSError with (socket.SOL_SOCKET, 0x1010, b'xxxx')

    Ok. Can you test my fix #144890 on Solaris?

  14. kulikjak commented on Feb 17, 2026

    @kulikjak
    Contributor

    Ok. Can you test my fix #144890 on Solaris?

    Thank you @vstinner - tested with all three affected runtimes and the issue is gone.

  15. added a commit that references this issue on Feb 17, 2026
  16. added 2 commits that reference this issue on Feb 17, 2026
  17. added 2 commits that reference this issue on Feb 17, 2026
  18. added 2 commits that reference this issue on Feb 28, 2026
  19. added 2 commits that reference this issue on Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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