-
Notifications
You must be signed in to change notification settings - Fork 340
Description
Checklist (Please check before submitting)
- I reviewed the Contributing Guide.
- I performed a cursory search to see if the bug report is relevant, not redundant, nor in conflict with other tickets.
Describe the bug
CFE_SB_TransmitMsg() reads the message size from the CCSDS header and uses it as the memcpy length when copying from the caller's buffer to a new Software Bus buffer. The API has no SourceBufferSize parameter, so there is no way to validate that the caller's buffer actually contains the claimed number of bytes. If the CCSDS Length field exceeds the source buffer allocation, memcpy reads past the buffer into adjacent memory, and the over-read data is delivered to all subscribers of that message ID.
This is the systemic root cause behind multiple downstream findings: the TO_LAB UDP over-read (Heartbleed-pattern), the sch_lab table over-read, and the zero-copy size mismatch. Addressing this at the SB API level remediates all of them simultaneously.
On flat-memory RTOS deployments (VxWorks, RTEMS) without MMU isolation, this enables cross-application information disclosure. The maximum over-read is bounded by CFE_MISSION_SB_MAX_SB_MSG_SIZE (default 32,768 bytes).
To Reproduce
- Allocate a small message buffer (e.g. 32 bytes) on the heap
- Set the CCSDS Length field to claim a much larger size (e.g. 1024 bytes)
- Call
CFE_SB_TransmitMsg()with this buffer - The internal
memcpyreads 1024 bytes from the 32-byte buffer - 992 bytes of adjacent memory are copied into the SB buffer and delivered to all subscribers - Confirmed with ASan:
heap-buffer-overflow READ of size 1024from a 32-byte region
Proof-of-concept source and ASan output are available upon request.
Expected behavior
CFE_SB_TransmitMsg() should validate that the CCSDS-derived message size does not exceed the actual source buffer size before performing the memcpy.
Code snips
API signature — no source buffer size parameter:
CFE_Status_t CFE_SB_TransmitMsg(const CFE_MSG_Message_t *MsgPtr, bool IsOrigination);Step 1 — Read size from CCSDS header (cfe_sb_priv.c:861-893):
CFE_MSG_GetSize(MsgPtr, &MsgSize);
CFE_SB_MessageTxn_SetContentSize(TxnPtr, MsgSize);Step 2 — Allocate destination buffer using CCSDS-derived size (cfe_sb_api.c:1491):
BufPtr = CFE_SB_AllocateMessageBuffer(CFE_SB_MessageTxn_GetContentSize(Txn));Step 3 — memcpy using CCSDS size with no source bounds validation (cfe_sb_api.c:1513):
memcpy(&BufPtr->Msg, MsgPtr, CFE_SB_MessageTxn_GetContentSize(Txn));System observed on:
- Hardware: x86_64
- OS: Linux (Ubuntu 22.04, with ASan)
- Versions: cFS Draco release, commit
83c735e
Additional context
This is the most architecturally significant finding in the assessment. The Software Bus is the central message-passing mechanism in cFS — every application uses CFE_SB_TransmitMsg(). The CCSDS Length field is trusted as the sole source of truth for buffer sizing throughout the entire framework. Fixing this at the API level hardens the entire message path.