Summary
The crsf_rc parser accepts an oversized variable-length known packet and copies it into a fixed 64-byte global buffer without a bounds check. In deployments where crsf_rc is enabled on a CRSF serial port, an adjacent/raw-serial attacker can trigger memory corruption and crash PX4.
Details
The issue is in src/drivers/rc/crsf_rc.
crsf_rc uses a fixed parser scratch buffer:
process_buffer[64] in src/drivers/rc/crsf_rc/CrsfParser.cpp
It also treats CRSF_PACKET_TYPE_ELRS_STATUS as a known variable-length packet:
CRSF_PAYLOAD_SIZE_ELRS_STATUS = -1
In the parser state machine, variable-length known packets do not pass through the same maximum-length rejection used for unknown packet types. The parser then copies working_index + CRC_SIZE bytes into process_buffer through QueueBuffer_PeekBuffer(), which performs an unchecked memcpy into the destination buffer.
This allows an oversized known packet to overflow process_buffer before CRC validation completes.
Relevant code locations:
src/drivers/rc/crsf_rc/CrsfParser.cpp:56
src/drivers/rc/crsf_rc/CrsfParser.cpp:67
src/drivers/rc/crsf_rc/CrsfParser.cpp:138
src/drivers/rc/crsf_rc/CrsfParser.cpp:399
src/drivers/rc/crsf_rc/CrsfParser.cpp:445
src/drivers/rc/crsf_rc/QueueBuffer.cpp:153
PoC
An integrated Docker-based reproduction environment is included under security-lab/crsf_rc.
Steps:
cd security-lab/crsf_rc
./run.sh
What the lab does:
- builds a real PX4 SITL binary with ASAN
- starts a real PX4 daemon
- starts the real
crsf_rc module against a PTY-backed serial device
- injects a crafted oversized
ELRS_STATUS frame through the PTY master
- extracts the in-container logs and validates the resulting ASAN crash
Expected evidence in logs/px4_crsf_rc_integration.log:
AddressSanitizer
global-buffer-overflow
QueueBuffer.cpp:153
CrsfParser.cpp:445
Confirmed result:
logs/crsf_rc_result.env contains triggered=true
Test-environment note:
- The integrated reproduction uses a POSIX PTY as a stand-in for the CRSF UART path.
- A small
LD_PRELOAD baud shim is used only because the host PTY environment cannot open the requested 420000 baud setting directly.
- In practical terms, this reproduces the software-equivalent of an attacker being physically connected to the drone's CRSF UART path and injecting raw serial bytes into the real
crsf_rc driver.
- The vulnerable PX4 parser logic is unchanged. The shim only adapts the PTY baud setup used for the lab.
Impact
- Vulnerability type: global/static buffer overflow
- Primary impact: denial of service through PX4 process crash
- Secondary impact: memory corruption and undefined behavior
Attack surface:
- This is not an internet-routable network issue.
- The realistic attacker model is an adjacent/raw-serial attacker that can inject bytes on the CRSF UART path, such as:
- a malicious CRSF/ExpressLRS receiver
- a UART man-in-the-middle device between receiver and flight controller
- a compromised external peripheral on the same serial path
- This report does not claim a pure RF-only unauthenticated remote exploit against standard CRSF equipment.
Attachment
security-lab_crsf_rc_20260312_204136.zip
Summary
The
crsf_rcparser accepts an oversized variable-length known packet and copies it into a fixed 64-byte global buffer without a bounds check. In deployments wherecrsf_rcis enabled on a CRSF serial port, an adjacent/raw-serial attacker can trigger memory corruption and crash PX4.Details
The issue is in
src/drivers/rc/crsf_rc.crsf_rcuses a fixed parser scratch buffer:process_buffer[64]insrc/drivers/rc/crsf_rc/CrsfParser.cppIt also treats
CRSF_PACKET_TYPE_ELRS_STATUSas a known variable-length packet:CRSF_PAYLOAD_SIZE_ELRS_STATUS = -1In the parser state machine, variable-length known packets do not pass through the same maximum-length rejection used for unknown packet types. The parser then copies
working_index + CRC_SIZEbytes intoprocess_bufferthroughQueueBuffer_PeekBuffer(), which performs an uncheckedmemcpyinto the destination buffer.This allows an oversized known packet to overflow
process_bufferbefore CRC validation completes.Relevant code locations:
src/drivers/rc/crsf_rc/CrsfParser.cpp:56src/drivers/rc/crsf_rc/CrsfParser.cpp:67src/drivers/rc/crsf_rc/CrsfParser.cpp:138src/drivers/rc/crsf_rc/CrsfParser.cpp:399src/drivers/rc/crsf_rc/CrsfParser.cpp:445src/drivers/rc/crsf_rc/QueueBuffer.cpp:153PoC
An integrated Docker-based reproduction environment is included under
security-lab/crsf_rc.Steps:
cd security-lab/crsf_rc ./run.shWhat the lab does:
crsf_rcmodule against a PTY-backed serial deviceELRS_STATUSframe through the PTY masterExpected evidence in
logs/px4_crsf_rc_integration.log:AddressSanitizerglobal-buffer-overflowQueueBuffer.cpp:153CrsfParser.cpp:445Confirmed result:
logs/crsf_rc_result.envcontainstriggered=trueTest-environment note:
LD_PRELOADbaud shim is used only because the host PTY environment cannot open the requested420000baud setting directly.crsf_rcdriver.Impact
Attack surface:
Attachment
security-lab_crsf_rc_20260312_204136.zip