[SECURITY] OOB Heap Read in CF_CFDP_CopyStringFromLV via Unvalidated PDU LV Length Field — Remotely Triggerable via Crafted Metadata PDU
Describe the bug
CF_CFDP_CopyStringFromLV() in fsw/src/cf_cfdp.c performs a memcpy using the attacker-supplied src_lv->length field from an incoming CFDP PDU without validating that the claimed length does not exceed the actual data present in the decode buffer. The only guard check (src_lv->length < buf_maxsz) compares against the destination buffer size, not against the remaining source PDU data. A remote attacker can send a specially crafted CFDP Metadata PDU containing an LV (Length-Value) field where the length octet claims a size far larger than the actual encoded payload — e.g., length = 0xFF (255) with only 3 bytes of filename data following it. The memcpy will then read ~252 bytes past the end of the allocated PDU buffer, disclosing adjacent heap memory contents into the destination string buffer.
This is the same class of vulnerability as:
- CVE-2026-5474 — TO_LAB CCSDS length OOB read
- cFE #2698 — SB transmit path missing lower-bound validation on CCSDS Length
Root Cause
In CF_CFDP_CopyStringFromLV(), the only validation is:
if (src_lv->length < buf_maxsz) // checks DESTINATION size, not SOURCE availability
{
memcpy(buf, src_lv->data_ptr, src_lv->length); // OOB read when length > actual PDU data
}
The function lacks access to the codec state (remaining PDU buffer size), so it cannot validate src_lv->length against the actual source data bounds. This is a systemic issue: the CFDP decoder fills CF_Logical_Lv_t fields based on attacker-controlled PDU bytes without any cross-validation that the claimed LV payload fits within the received PDU.
To Reproduce
- Establish a CFDP channel. No authentication is required on default NOS3 deployments.
- Craft a CFDP Metadata PDU (PDU type=0, directive code=0x00 for Metadata) with:
- Valid source/destination EID matching the local CF entity
- Valid transaction sequence number
- Source filename LV:
length = 0xFF (255), actual data = 3 bytes
- Destination filename LV:
length = 0xFF (255), actual data = 3 bytes
- Send the PDU to the CF input MID via UDP (e.g., via CI_LAB passthrough)
CF_CFDP_ReceivePdu() → CF_CFDP_RecvPh() → CF_CFDP_RecvMd() → CF_CFDP_CopyStringFromLV()
memcpy reads from src_lv->data_ptr for src_lv->length bytes, far beyond the actual 3 bytes of filename data, into adjacent heap memory
- The excess heap data ends up in
txn->history->fnames.src_filename and can be exfiltrated via subsequent CFDP ACK/MD PDUs or EOT telemetry
Expected behavior
CF_CFDP_CopyStringFromLV() must validate src_lv->length against the actual remaining data in the PDU decode buffer before performing memcpy. If insufficient data remains, the function must return CF_ERROR without copying.
Proposed Fix
The function signature needs access to the codec state to know how much source data remains. Two approaches:
Approach A (Minimal — pass remaining PDU size):
Modify CF_CFDP_CopyStringFromLV() to accept an additional remaining_pdu_bytes parameter from the caller, and validate:
int CF_CFDP_CopyStringFromLV(char *buf, size_t buf_maxsz, const CF_Logical_Lv_t *src_lv, size_t remaining_pdu_bytes)
{
if (src_lv->data_ptr != NULL
&& src_lv->length <= remaining_pdu_bytes // ← validate against actual PDU data available
&& src_lv->length < buf_maxsz) // ← validate against destination buffer
{
memcpy(buf, src_lv->data_ptr, src_lv->length);
buf[src_lv->length] = 0;
return src_lv->length;
}
buf[0] = 0;
return CF_ERROR;
}
Approach B (Robust — validate at decode time):
Validate the LV length during CF_CFDP_DecodeMd() (or wherever the LV is parsed from the PDU) while the codec state still knows the remaining buffer size. If the LV claims more bytes than available, set a decode error immediately rather than deferring the check.
Call sites that need updating:
CF_CFDP_RecvMd() — passes md->source_filename and md->dest_filename to CF_CFDP_CopyStringFromLV()
Code snips
File: fsw/src/cf_cfdp.c, lines near 2209-2242:
int CF_CFDP_CopyStringFromLV(char *buf, size_t buf_maxsz, const CF_Logical_Lv_t *src_lv)
{
if (src_lv->length < buf_maxsz) // BUG: only checks destination
{
memcpy(buf, src_lv->data_ptr, src_lv->length); // BUG: no source bounds check
buf[src_lv->length] = 0;
return src_lv->length;
}
buf[0] = 0;
return CF_ERROR;
}
System observed on
- Hardware: x86-64 (POSIX cFS / NOS3 simulator)
- OS: Linux 6.8.0 (Ubuntu 24.04)
- Versions: CF bundle @ latest commit (Draco v7.0.0), CFE v7.0.0-rc4+dev370
Additional context
- Remotely triggerable via any CFDP Metadata PDU. No prior authentication or handshake required.
- The leaked heap region typically contains PDU buffer descriptors, transaction history structures (including peer EIDs, sequence numbers, and filenames from previous transfers), and potentially libc/mmap pointers.
- After the OOB read into the filename buffer, the data may be sent back in subsequent ACK PDUs or End-of-Transaction telemetry — providing an exfiltration path.
[SECURITY] OOB Heap Read in CF_CFDP_CopyStringFromLV via Unvalidated PDU LV Length Field — Remotely Triggerable via Crafted Metadata PDU
Describe the bug
CF_CFDP_CopyStringFromLV()infsw/src/cf_cfdp.cperforms amemcpyusing the attacker-suppliedsrc_lv->lengthfield from an incoming CFDP PDU without validating that the claimed length does not exceed the actual data present in the decode buffer. The only guard check (src_lv->length < buf_maxsz) compares against the destination buffer size, not against the remaining source PDU data. A remote attacker can send a specially crafted CFDP Metadata PDU containing an LV (Length-Value) field where the length octet claims a size far larger than the actual encoded payload — e.g.,length = 0xFF(255) with only 3 bytes of filename data following it. Thememcpywill then read ~252 bytes past the end of the allocated PDU buffer, disclosing adjacent heap memory contents into the destination string buffer.This is the same class of vulnerability as:
Root Cause
In CF_CFDP_CopyStringFromLV(), the only validation is:
The function lacks access to the codec state (remaining PDU buffer size), so it cannot validate
src_lv->lengthagainst the actual source data bounds. This is a systemic issue: the CFDP decoder fillsCF_Logical_Lv_tfields based on attacker-controlled PDU bytes without any cross-validation that the claimed LV payload fits within the received PDU.To Reproduce
length = 0xFF(255), actual data = 3 byteslength = 0xFF(255), actual data = 3 bytesCF_CFDP_ReceivePdu()→CF_CFDP_RecvPh()→CF_CFDP_RecvMd()→CF_CFDP_CopyStringFromLV()memcpyreads fromsrc_lv->data_ptrforsrc_lv->lengthbytes, far beyond the actual 3 bytes of filename data, into adjacent heap memorytxn->history->fnames.src_filenameand can be exfiltrated via subsequent CFDP ACK/MD PDUs or EOT telemetryExpected behavior
CF_CFDP_CopyStringFromLV()must validatesrc_lv->lengthagainst the actual remaining data in the PDU decode buffer before performingmemcpy. If insufficient data remains, the function must returnCF_ERRORwithout copying.Proposed Fix
The function signature needs access to the codec state to know how much source data remains. Two approaches:
Approach A (Minimal — pass remaining PDU size):
Modify
CF_CFDP_CopyStringFromLV()to accept an additionalremaining_pdu_bytesparameter from the caller, and validate:Approach B (Robust — validate at decode time):
Validate the LV length during
CF_CFDP_DecodeMd()(or wherever the LV is parsed from the PDU) while the codec state still knows the remaining buffer size. If the LV claims more bytes than available, set a decode error immediately rather than deferring the check.Call sites that need updating:
CF_CFDP_RecvMd()— passesmd->source_filenameandmd->dest_filenametoCF_CFDP_CopyStringFromLV()Code snips
File:
fsw/src/cf_cfdp.c, lines near 2209-2242:System observed on
Additional context