AFLplusplus / AFLplusplus/LibAFL

libafl-qemu: multiple consecutive `load_snapshot` calls cause segmentation fault

Open
#2,746 1 comment 0 reactions 1 assignee Claimed by @rmalmain View on GitHub
bug qemu
Dominant language
Rust
Stars
2.6k
Forks
481
Avg merge
2d 30m
Merged PRs (30d)
16

Description

Like @langston-barrett in #2628, I'm trying to fuzz an EDKII image while using snapshots. I'm running into an issue where restoring a snapshot twice in a row, without starting/restarting QEMU in between those restorations, will reliably cause a segmentation fault once QEMU restarts. (Also like Langston, I can't share the compiled artifacts used here, but I strongly suspect the issue is independent of them, and should be replicable with another systemmode target.) Consider this example:
```rs
// cargo init
// cargo add --no-default-features --features=systemmode --git https://github.com/AFLplusplus/LibAFL libafl_qemu
// cargo run

use std::error;

const QEMU_FLAGS: &[&str] = &[
"-machine",
"q35",
"-kernel",
"./impl/bzImage",
"-append",
"'rootwait root=/dev/vda console=tty1 console=ttyS0 keep_bootcon'",
"-drive",
"file=./impl/rootfs.ext2,if=virtio,format=raw,readonly=on",
"-global",
"driver=cfi.pflash01,property=secure,value=on",
"-drive",
"if=pflash,format=raw,unit=1,file=./impl/OVMF_VARS.fd",
"-drive",
"if=pflash,format=raw,unit=0,readonly=on,file=./impl/OVMF_CODE.fd",
"-smp",
"2",
"-m",
"4G",
"-bios",
"./impl/OVMF.fd",
"-snapshot",
"-S",
"-nodefaults",
];

const SNAPSHOT_NAME: &'static str = "snapshot";
const SYNC: bool = true;

fn main() -> Result<(), Box> {
let mut args = vec!["qemu".to_owned()];
args.extend(QEMU_FLAGS.iter().map(|s| (*s).to_owned()));
let qemu = libafl_qemu::Qemu::init(args.as_slice())?;

let entry = 0x7FFA3C01;

println!("Saving snapshot...");
qemu.save_snapshot(SNAPSHOT_NAME, SYNC);

println!("Loading snapshot...");
qemu.load_snapshot(SNAPSHOT_NAME, SYNC);

// println!("Loading snapshot again...");
// qemu.load_snapshot(SNAPSHOT_NAME, SYNC);

println!("Running to {entry:#x}...");
qemu.entry_break(entry);
println!("...finished.");

Ok(())
}
```

Without the second `load_snapshot`, I see this run to completion. With the second `load_snapshot`, I get a segmentation fault when QEMU restarts:
```
rom: file kvmvapic.bin : error Failed to open file “kvmvapic.bin”: No such file or directory
rom: file linuxboot_dma.bin : error Failed to open file “linuxboot_dma.bin”: No such file or directory
Saving snapshot...
Loading snapshot...
Loading snapshot again...
Running to 0x7ffa3c01...
Segmentation fault (core dumped)
```

Here's a backtrace:
```
Saving snapshot...
Loading snapshot...
Loading snapshot again...
Running to 0x7ffa3c01...

Thread 1 "scratch" received signal SIGSEGV, Segmentation fault.
0x00005555571c68c0 in ?? ()
(gdb) bt
#0 0x00005555571c68c0 in ?? ()
#1 0x0000555555a6e604 in vm_state_notify (running=running@entry=true, state=state@entry=RUN_STATE_RUNNING) at ../system/runstate.c:399
#2 0x0000555555a64fca in vm_prepare_start (step_pending=step_pending@entry=false) at ../system/cpus.c:778
#3 0x0000555555a65034 in vm_start () at ../system/cpus.c:799
#4 0x00005555558609db in libafl_qemu::qemu::Qemu::run_inner (self=0x7fffffffd917) at src/qemu/systemmode.rs:219
#5 0x000055555586116b in libafl_qemu::qemu::Qemu::run (self=0x7fffffffd917) at src/qemu/mod.rs:668
#6 0x000055555586147e in libafl_qemu::qemu::Qemu::entry_break (self=0x7fffffffd917, addr=2147105793) at src/qemu/mod.rs:864
#7 0x000055555585f3c5 in scratch::main () at src/main.rs:53
(gdb)
```

I've done some digging and hypothesize that this might be due to a bug in `qemu-libafl-bridge`, so let me know if I ought to move discussion to an issue there instead.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.