Skip to content

sctp_recv_msg crashes because interpret_notification inserts NULL into dict #56

@lyyffee

Description

@lyyffee

Environment:

  • Ubuntu 22.04, kernel 6.8.0-87-generic
  • Python 3.10.12 (python3.10-dbg installed)
  • pysctp 0.7.2 (pip install), _sctp.so linked to /lib/x86_64-linux-gnu/libsctp.so.1

Problem:
When sctp_recv_msg handles SCTP_SEND_FAILED or SCTP_REMOTE_ERROR notifications whose payload is arbitrary binary data, interpret_notification() calls PyUnicode_FromStringAndSize(cdata, ldata). If the bytes are not valid UTF-8 (or allocation fails), this function returns NULL. The code immediately calls PyDict_SetItemString(dict, "data", NULL), which leads to _Py_INCREF(NULL) and a SIGSEGV.

Crash backtrace (python3.10-dbg + core dump):

#5  _Py_INCREF(op=0x0)
#6  insertdict(... value=0x0) at dictobject.c:1075
#7  PyDict_SetItem(...)
#8  PyDict_SetItemString(... item=0x0)
#9  interpret_notification(dict=..., pnotif=..., size=...) at _sctp.c:1815
#10 sctp_recv_msg(...) at _sctp.c:1865

Expected behavior:
If the notification payload cannot be converted to a Unicode object, the function should either raise a Python exception or store the data as bytes. It must never insert NULL into the dictionary.

Actual behavior:
The Python interpreter crashes whenever a send-failure / remote-error notification contains non UTF-8 data.

How to reproduce:

  1. Enable SCTP send_failure and peer_error events.
  2. Send data that triggers SCTP_SEND_FAILED (or a remote error) with non-UTF8 payload.
  3. Call sctp.sctp_recv() in Python; as soon as the notification arrives, python3 crashes with SIGSEGV.

Suggested fix:
Treat “data” as bytes and check for NULL before inserting into the dict.

Possible patch:

  case SCTP_SEND_FAILED: {
       ...
       if (ldata >= 0) {
           PyObject* info = PyDict_New();
           PyObject* data_obj = PyBytes_FromStringAndSize(cdata, ldata);
           if (!info || !data_obj) {
               Py_XDECREF(info);
               Py_XDECREF(data_obj);
               return;
           }
           PyDict_SetItemString(dict, "_info", info);
           Py_DECREF(info);
           PyDict_SetItemString(dict, "error", Py23_PyLong_FromLong(n->ssf_error));
           PyDict_SetItemString(dict, "assoc_id", Py23_PyLong_FromLong(n->ssf_assoc_id));
           PyDict_SetItemString(dict, "data", data_obj);
           Py_DECREF(data_obj);
       }
       break;
   case SCTP_REMOTE_ERROR: {
       ...
       if (ldata >= 0) {
           PyObject* data_obj = PyBytes_FromStringAndSize(cdata, ldata);
           if (!data_obj) { return; }
           PyDict_SetItemString(dict, "error", Py23_PyLong_FromLong(n->sre_error));
           PyDict_SetItemString(dict, "assoc_id", Py23_PyLong_FromLong(n->sre_assoc_id));
           PyDict_SetItemString(dict, "data", data_obj);
           Py_DECREF(data_obj);
       }
       break;

Workaround:
None at Python level; any application receiving such a notification will crash.

Please confirm and repair it so that sctp_recv_msg no longer segfaults when notification payloads contain arbitrary binary data.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions