ArduPilot / ArduPilot/ardupilot

Crafted MAVLink Packet leads to hard fault

Open
#32,121 2 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.