ArduPilot / ArduPilot/ardupilot
Crafted MAVLink Packet leads to hard fault
- Dominant language
- C++
- Stars
- 15.9k
- Forks
- 21.4k
- Avg merge
- 3d 17h
- Merged PRs (30d)
- 119
Description
## Bug report
**Issue details**
I was fuzzing the mavlink handler inside of `GCS_MAVLINK::update_receive` and was crafting packets like so:
```
while (true) {
read_count = fuzz_buffer_read(last_anchor_id, g_fuzzing_input, sizeof(g_fuzzing_input));
if (read_count > 15 && read_count < 262) {
break;
}
fuzz_finish(last_anchor_id);
}
// one byte length
uint8_t length = g_fuzzing_input[0];
// 24-bits to msgid
uint32_t msgid =
((uint32_t)g_fuzzing_input[1] & 0xFF) << 16 |
((uint32_t)g_fuzzing_input[2] & 0xFF) << 8 |
((uint32_t)g_fuzzing_input[3] & 0xFF);
// get crc extra from mavlink message entry
const mavlink_msg_entry_t *mavlink_msg_entry = mavlink_get_msg_entry(msgid);
if (mavlink_msg_entry == NULL) {
// fprintf(stderr, "Unknown MAVLink message ID: %u\n", msgid);
fuzz_finish(last_anchor_id);
goto fuzz;
}
uint8_t crc_extra = mavlink_msg_entry->crc_extra;
uint8_t sys_id = g_fuzzing_input[4];
uint8_t comp_id = g_fuzzing_input[5];
// payload is rest of data
const uint8_t *payload = (const uint8_t *)&g_fuzzing_input[6];
// real length is total - 6 bytes
uint8_t real_length = read_count - 6;
assign_fuzzed_input(msgid, crc_extra, payload, length, real_length, sys_id, comp_id);
create_fuzzed_mavlink_packet(msgid, crc_extra, payload, length, real_length, sys_id, comp_id);
restore_registers();
```
During this campaign I found one packet that caused a hard fault. My environment is an my own orchestrated version of QEMU capable of rehosting ArduPilot vehicles and I believe these bugs are worth checking out on real hardware. I select all for the platform because the GCS_MAVLINK class is a library. See the logs to find my exact input/payload. I have yet to fully triage this one but it deterministically hard faults in my orchestrated QEMU instance
**Version**
ArduRover release v4.6.2
**Platform**
[X] All
[ ] AntennaTracker
[ ] Copter
[ ] Plane
[ ] Rover
[ ] Submarine
**Airframe type**
Rover
**Hardware type**
QEMU instance rehosting firmware designed for CubeBlack flight controller.
**Logs**
```
Length: 32, MsgID: 75, CRC Extra: 158, Real Length: 32, SysID: 126, CompID: 42
72 00 B4 9B 7F 97 00 FF 01 00 7F 00 00 00 20 47
B3 A2 6E 75 4C 82 00 91 91 91 10 00 91 01 00 65
```
Contributor guide
Research direction
Start at GCS_MAVLINK::update_receive and reproduce the deterministic hard fault using the logged 32-byte input in the QEMU rehosting environment. Trace the crafted MAVLink packet through the receive handler to identify the fault and its triggering bounds or validation condition. Done means the fault is prevented and the supplied packet is covered by a regression test or documented reproducer.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- embedded-iot, networking, security
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100