Current Behavior
When MSP-over-SmartPort sends a response, smartPortSendMspResponse() creates a local smartPortPayload_t without initializing it:
static void smartPortSendMspResponse(uint8_t *data, const uint8_t dataSize)
{
smartPortPayload_t payload;
payload.frameId = FSSP_MSPS_FRAME;
memcpy(&payload.valueId, data,
MIN(dataSize, SMARTPORT_MSP_PAYLOAD_SIZE));
smartPortWriteFrame(&payload);
}
Only dataSize bytes are copied into the six-byte MSP portion of the structure.
smartPortWriteFrameSerial() then serializes the complete smartPortPayload_t:
uint8_t *data = (uint8_t *)payload;
for (unsigned i = 0; i < sizeof(smartPortPayload_t); i++) {
smartPortSendByte(*data++, &checksum, port);
}
Therefore, when the final MSP response fragment contains fewer than SMARTPORT_MSP_PAYLOAD_SIZE bytes, the unused tail of the local stack object is transmitted without having been initialized by this function.
Affected source in the tested commit:
https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.c#L2104-L2118
https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.c#L2230-L2242
https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.h#L336-L337
https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.h#L372-L378
Security impact
This is an information-disclosure vulnerability across the flight-controller to SmartPort telemetry boundary.
When the final MSP response fragment is shorter than the fixed SmartPort MSP payload, the unused bytes of the stack-allocated smartPortPayload_t are not initialized before the complete structure is serialized.
A telemetry peer receiving those frames can therefore receive bytes originating from previous stack contents.
The exact contents depend on compiler, target and runtime stack reuse. I have not demonstrated leakage of credentials, keys or a specific secret, so the report should not claim disclosure of any particular sensitive value.
Attacker preconditions
The observing party must be the SmartPort telemetry peer (or otherwise be able to observe that telemetry link). This is not a generic Internet-facing information leak.
What is proven
- The short-copy/full-serialization pattern is present in the tested INAV source.
- MemorySanitizer confirms that the modeled transmit path consumes uninitialized bytes.
What is not proven
- Leakage of a specific secret from physical hardware.
- Exposure to peers that cannot observe the SmartPort telemetry channel.
Steps to Reproduce
I reproduced the initialization pattern with Clang MemorySanitizer.
This is a host-side sanitizer reproduction of the production initialization/transmit pattern, not a capture from a physical SmartPort bus.
Save as poc_inav_smartport_uninitialized.c:
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#define SMARTPORT_MSP_PAYLOAD_SIZE 6
#define FSSP_MSPS_FRAME 0x32
#define MIN(a,b) ((a) < (b) ? (a) : (b))
typedef struct __attribute__((packed)) {
uint8_t frameId;
uint16_t valueId;
uint32_t data;
} smartPortPayload_t;
static uint8_t consume_all_bytes(const smartPortPayload_t *p)
{
const uint8_t *b = (const uint8_t *)p;
uint8_t x = 0;
for (unsigned i = 0; i < sizeof(*p); i++) {
x ^= b[i];
}
return x;
}
static uint8_t vulnerable_send(uint8_t *data, uint8_t dataSize)
{
smartPortPayload_t payload;
payload.frameId = FSSP_MSPS_FRAME;
memcpy(&payload.valueId, data,
MIN(dataSize, SMARTPORT_MSP_PAYLOAD_SIZE));
return consume_all_bytes(&payload);
}
int main(void)
{
uint8_t one = 0x41;
volatile uint8_t sink = vulnerable_send(&one, 1);
printf("sink=%u\n", sink);
return 0;
}
Compile and run with Clang:
clang -O1 -g -fsanitize=memory -fno-omit-frame-pointer poc_inav_smartport_uninitialized.c -o poc_inav_smartport_uninitialized
./poc_inav_smartport_uninitialized
Observed locally:
WARNING: MemorySanitizer: use-of-uninitialized-value
The tested INAV tree was:
commit: c5c593d71d33c8e284bf9cd34381588fda7a98c8
date: 2026-07-18 22:18:56 -0500
subject: Merge pull request #11728 from iNavFlight/release/9.1
Expected behavior
All bytes of a telemetry frame should be initialized before the structure is serialized.
Short final MSP response fragments should contain deterministic padding rather than previous stack contents.
Suggested solution(s)
Zero-initialize the structure before filling it, for example:
smartPortPayload_t payload = {0};
payload.frameId = FSSP_MSPS_FRAME;
memcpy(&payload.valueId, data,
MIN(dataSize, SMARTPORT_MSP_PAYLOAD_SIZE));
Alternatively, explicitly zero the unused payload tail.
Additional context
Current Behavior
When MSP-over-SmartPort sends a response,
smartPortSendMspResponse()creates a localsmartPortPayload_twithout initializing it:Only
dataSizebytes are copied into the six-byte MSP portion of the structure.smartPortWriteFrameSerial()then serializes the completesmartPortPayload_t:Therefore, when the final MSP response fragment contains fewer than
SMARTPORT_MSP_PAYLOAD_SIZEbytes, the unused tail of the local stack object is transmitted without having been initialized by this function.Affected source in the tested commit:
https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.c#L2104-L2118https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.c#L2230-L2242https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.h#L336-L337https://github.com/iNavFlight/inav/blob/c5c593d71d33c8e284bf9cd34381588fda7a98c8/src/main/telemetry/smartport.h#L372-L378Security impact
This is an information-disclosure vulnerability across the flight-controller to SmartPort telemetry boundary.
When the final MSP response fragment is shorter than the fixed SmartPort MSP payload, the unused bytes of the stack-allocated
smartPortPayload_tare not initialized before the complete structure is serialized.A telemetry peer receiving those frames can therefore receive bytes originating from previous stack contents.
The exact contents depend on compiler, target and runtime stack reuse. I have not demonstrated leakage of credentials, keys or a specific secret, so the report should not claim disclosure of any particular sensitive value.
Attacker preconditions
The observing party must be the SmartPort telemetry peer (or otherwise be able to observe that telemetry link). This is not a generic Internet-facing information leak.
What is proven
What is not proven
Steps to Reproduce
I reproduced the initialization pattern with Clang MemorySanitizer.
This is a host-side sanitizer reproduction of the production initialization/transmit pattern, not a capture from a physical SmartPort bus.
Save as
poc_inav_smartport_uninitialized.c:Compile and run with Clang:
Observed locally:
The tested INAV tree was:
Expected behavior
All bytes of a telemetry frame should be initialized before the structure is serialized.
Short final MSP response fragments should contain deterministic padding rather than previous stack contents.
Suggested solution(s)
Zero-initialize the structure before filling it, for example:
Alternatively, explicitly zero the unused payload tail.
Additional context