LibAFL QEMU update to v10.0.0 (#3181)

* update qemu hash

* clippy, fmt

* update

* Revert "Update hashbrown requirement from 0.14.5 to 0.15.3 (#3184)" (#3186)

This reverts commit 4448799dc2205e4cb1753b8b8d91b4f6d299365d.

* update qemu

* fix systemmode

* update qemu

* update qemu

* update qemu with fix

* debug

* cargo hack

* FMT

---------

Co-authored-by: Dongjia Zhang <tokazerkje@outlook.com>
This commit is contained in:
Romain Malmain 2025-05-12 07:58:11 -07:00 committed by GitHub
parent 0d962bc561
commit c9b0dc216f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 1544 additions and 1343 deletions

View File

@ -23,9 +23,10 @@ runs:
- name: Add nightly clippy - name: Add nightly clippy
shell: bash shell: bash
run: rustup toolchain install nightly --component clippy --allow-downgrade run: rustup toolchain install nightly --component clippy --allow-downgrade
- name: Install cargo-hack - uses: taiki-e/install-action@cargo-hack
- name: Add nightly
shell: bash shell: bash
run: curl -LsSf https://github.com/taiki-e/cargo-hack/releases/latest/download/cargo-hack-x86_64-unknown-linux-gnu.tar.gz | tar xzf - -C ~/.cargo/bin run: rustup toolchain install nightly --allow-downgrade
- name: Default to nightly - name: Default to nightly
shell: bash shell: bash
run: rustup default nightly run: rustup default nightly

View File

@ -53,9 +53,8 @@ const WRAPPER_HEADER: &str = r#"
#include "migration/savevm.h" #include "migration/savevm.h"
#include "hw/core/sysemu-cpu-ops.h" #include "hw/core/sysemu-cpu-ops.h"
#include "exec/address-spaces.h" #include "exec/address-spaces.h"
#include "sysemu/tcg.h" #include "exec/target_page.h"
#include "sysemu/runstate.h" #include "system/system.h"
#include "sysemu/replay.h"
#include "libafl/system.h" #include "libafl/system.h"
#include "libafl/qemu_snapshot.h" #include "libafl/qemu_snapshot.h"
@ -67,11 +66,9 @@ const WRAPPER_HEADER: &str = r#"
#include "exec/cpu-common.h" #include "exec/cpu-common.h"
#include "exec/cpu-all.h" #include "exec/cpu-all.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/translate-all.h"
#include "exec/log.h" #include "exec/log.h"
#include "trace/trace-root.h" #include "trace/trace-root.h"
#include "qemu/accel.h" #include "qemu/accel.h"
#include "hw/core/accel-cpu.h"
#include "tcg/tcg.h" #include "tcg/tcg.h"
#include "tcg/tcg-op.h" #include "tcg/tcg-op.h"
@ -122,6 +119,7 @@ pub fn generate(
.derive_default(true) .derive_default(true)
.impl_debug(true) .impl_debug(true)
.generate_comments(true) .generate_comments(true)
.wrap_static_fns(true)
.default_enum_style(bindgen::EnumVariation::NewType { .default_enum_style(bindgen::EnumVariation::NewType {
is_global: true, is_global: true,
is_bitfield: true, is_bitfield: true,

View File

@ -11,7 +11,7 @@ use crate::cargo_add_rpath;
pub const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge"; pub const QEMU_URL: &str = "https://github.com/AFLplusplus/qemu-libafl-bridge";
pub const QEMU_DIRNAME: &str = "qemu-libafl-bridge"; pub const QEMU_DIRNAME: &str = "qemu-libafl-bridge";
pub const QEMU_REVISION: &str = "97bef506eed24ee8d0eda4a07c4419c55dae4acb"; pub const QEMU_REVISION: &str = "0bea78a122b249cbffafdb130af04cc7331c9aee";
pub struct BuildResult { pub struct BuildResult {
pub qemu_path: PathBuf, pub qemu_path: PathBuf,

View File

@ -6,6 +6,7 @@
#![expect(improper_ctypes)] #![expect(improper_ctypes)]
#![expect(unsafe_op_in_unsafe_fn)] #![expect(unsafe_op_in_unsafe_fn)]
#![allow(unused_imports)] #![allow(unused_imports)]
#![allow(unnecessary_transmutes)]
#[cfg(all(not(feature = "clippy"), target_os = "linux"))] #[cfg(all(not(feature = "clippy"), target_os = "linux"))]
#[rustfmt::skip] #[rustfmt::skip]

View File

@ -1,5 +1,5 @@
/* 1.87.0-nightly */ /* 1.88.0-nightly */
/* qemu git hash: 97bef506eed24ee8d0eda4a07c4419c55dae4acb */ /* qemu git hash: 93663809156a33475ade972cdd5b1301b9310687 */
/* automatically generated by rust-bindgen 0.71.1 */ /* automatically generated by rust-bindgen 0.71.1 */
#[repr(C)] #[repr(C)]
@ -661,17 +661,19 @@ impl Default for _IO_FILE {
impl _IO_FILE { impl _IO_FILE {
#[inline] #[inline]
pub fn _flags2(&self) -> ::std::os::raw::c_int { pub fn _flags2(&self) -> ::std::os::raw::c_int {
u32::cast_signed(self._bitfield_1.get(0usize, 24u8) as u32) unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) }
} }
#[inline] #[inline]
pub fn set__flags2(&mut self, val: ::std::os::raw::c_int) { pub fn set__flags2(&mut self, val: ::std::os::raw::c_int) {
let val: u32 = i32::cast_unsigned(val); unsafe {
self._bitfield_1.set(0usize, 24u8, val as u64) let val: u32 = ::std::mem::transmute(val);
self._bitfield_1.set(0usize, 24u8, val as u64)
}
} }
#[inline] #[inline]
pub unsafe fn _flags2_raw(this: *const Self) -> ::std::os::raw::c_int { pub unsafe fn _flags2_raw(this: *const Self) -> ::std::os::raw::c_int {
unsafe { unsafe {
u32::cast_signed(<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_get( ::std::mem::transmute(<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_get(
::std::ptr::addr_of!((*this)._bitfield_1), ::std::ptr::addr_of!((*this)._bitfield_1),
0usize, 0usize,
24u8, 24u8,
@ -681,7 +683,7 @@ impl _IO_FILE {
#[inline] #[inline]
pub unsafe fn set__flags2_raw(this: *mut Self, val: ::std::os::raw::c_int) { pub unsafe fn set__flags2_raw(this: *mut Self, val: ::std::os::raw::c_int) {
unsafe { unsafe {
let val: u32 = i32::cast_unsigned(val); let val: u32 = ::std::mem::transmute(val);
<__BindgenBitfieldUnit<[u8; 3usize]>>::raw_set( <__BindgenBitfieldUnit<[u8; 3usize]>>::raw_set(
::std::ptr::addr_of_mut!((*this)._bitfield_1), ::std::ptr::addr_of_mut!((*this)._bitfield_1),
0usize, 0usize,
@ -694,7 +696,7 @@ impl _IO_FILE {
pub fn new_bitfield_1(_flags2: ::std::os::raw::c_int) -> __BindgenBitfieldUnit<[u8; 3usize]> { pub fn new_bitfield_1(_flags2: ::std::os::raw::c_int) -> __BindgenBitfieldUnit<[u8; 3usize]> {
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default(); let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 3usize]> = Default::default();
__bindgen_bitfield_unit.set(0usize, 24u8, { __bindgen_bitfield_unit.set(0usize, 24u8, {
let _flags2: u32 = i32::cast_unsigned(_flags2); let _flags2: u32 = unsafe { ::std::mem::transmute(_flags2) };
_flags2 as u64 _flags2 as u64
}); });
__bindgen_bitfield_unit __bindgen_bitfield_unit

View File

@ -1,5 +1,5 @@
/* 1.87.0-nightly */ /* 1.88.0-nightly */
/* qemu git hash: 97bef506eed24ee8d0eda4a07c4419c55dae4acb */ /* qemu git hash: 93663809156a33475ade972cdd5b1301b9310687 */
/* automatically generated by rust-bindgen 0.71.1 */ /* automatically generated by rust-bindgen 0.71.1 */
#[repr(C)] #[repr(C)]

View File

@ -44,6 +44,7 @@ mod bindings {
#![expect(clippy::all)] #![expect(clippy::all)]
#![expect(clippy::pedantic)] #![expect(clippy::pedantic)]
#![allow(unsafe_op_in_unsafe_fn)] #![allow(unsafe_op_in_unsafe_fn)]
#![allow(unnecessary_transmutes)]
include!(concat!(env!("OUT_DIR"), "/libafl_qemu_bindings.rs")); include!(concat!(env!("OUT_DIR"), "/libafl_qemu_bindings.rs"));
} }

View File

@ -49,6 +49,7 @@ pub(crate) mod bindings {
#![allow(unused_variables)] #![allow(unused_variables)]
#![expect(clippy::all)] #![expect(clippy::all)]
#![expect(clippy::pedantic)] #![expect(clippy::pedantic)]
#![allow(unnecessary_transmutes)]
include!(concat!(env!("OUT_DIR"), "/nyx_bindings.rs")); include!(concat!(env!("OUT_DIR"), "/nyx_bindings.rs"));
} }

View File

@ -77,7 +77,8 @@ where
qemu: Qemu, qemu: Qemu,
arch_regs_map: &'static EnumMap<ExitArgs, Regs>, arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
) -> Result<Self::OutputCommand, CommandError> { ) -> Result<Self::OutputCommand, CommandError> {
let input_virt_addr: GuestVirtAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into(); let input_virt_addr: GuestVirtAddr =
qemu.read_reg(arch_regs_map[ExitArgs::Arg1])? as GuestVirtAddr;
let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?; let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?;
Ok(InputCommand::new( Ok(InputCommand::new(
@ -134,7 +135,8 @@ where
qemu: Qemu, qemu: Qemu,
arch_regs_map: &'static EnumMap<ExitArgs, Regs>, arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
) -> Result<Self::OutputCommand, CommandError> { ) -> Result<Self::OutputCommand, CommandError> {
let input_virt_addr: GuestVirtAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into(); let input_virt_addr: GuestVirtAddr =
qemu.read_reg(arch_regs_map[ExitArgs::Arg1])? as GuestVirtAddr;
let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?; let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?;
Ok(StartCommand::new(QemuMemoryChunk::virt( Ok(StartCommand::new(QemuMemoryChunk::virt(

View File

@ -6,7 +6,7 @@ use libafl_qemu_sys::GuestVirtAddr;
use libc::c_uint; use libc::c_uint;
use crate::{ use crate::{
IsSnapshotManager, NyxEmulatorDriver, Qemu, QemuMemoryChunk, Regs, GuestReg, IsSnapshotManager, NyxEmulatorDriver, Qemu, QemuMemoryChunk, Regs,
command::{ command::{
CommandError, NativeExitKind, CommandError, NativeExitKind,
nyx::{ nyx::{
@ -26,7 +26,7 @@ fn get_guest_string(qemu: Qemu, string_ptr_reg: Regs) -> Result<String, CommandE
let mut msg_chunk: [u8; bindings::HPRINTF_MAX_SIZE as usize] = let mut msg_chunk: [u8; bindings::HPRINTF_MAX_SIZE as usize] =
[0; bindings::HPRINTF_MAX_SIZE as usize]; [0; bindings::HPRINTF_MAX_SIZE as usize];
qemu.read_mem(str_addr, &mut msg_chunk)?; qemu.read_mem(str_addr.try_into().unwrap(), &mut msg_chunk)?;
Ok(CStr::from_bytes_until_nul(&msg_chunk) Ok(CStr::from_bytes_until_nul(&msg_chunk)
.unwrap() .unwrap()
@ -117,7 +117,7 @@ where
// # Safety // # Safety
// Range submit is represented with an array of 3 u64 in the Nyx API. // Range submit is represented with an array of 3 u64 in the Nyx API.
let allowed_range: [u64; 3] = unsafe { qemu.read_mem_val(allowed_range_addr)? }; let allowed_range: [u64; 3] = unsafe { qemu.read_mem_val(allowed_range_addr as u64)? };
Ok(RangeSubmitCommand::new(allowed_range[0]..allowed_range[1])) Ok(RangeSubmitCommand::new(allowed_range[0]..allowed_range[1]))
} }
@ -245,7 +245,7 @@ where
Ok(GetHostConfigCommand::new(QemuMemoryChunk::virt( Ok(GetHostConfigCommand::new(QemuMemoryChunk::virt(
host_config_addr, host_config_addr,
GuestVirtAddr::try_from(size_of::<bindings::host_config_t>()).unwrap(), GuestReg::try_from(size_of::<bindings::host_config_t>()).unwrap(),
qemu.current_cpu().unwrap(), qemu.current_cpu().unwrap(),
))) )))
} }
@ -270,7 +270,7 @@ where
// # Safety // # Safety
// We use the C struct directly to get the agent config // We use the C struct directly to get the agent config
let agent_config: bindings::agent_config_t = let agent_config: bindings::agent_config_t =
unsafe { qemu.read_mem_val(agent_config_addr)? }; unsafe { qemu.read_mem_val(agent_config_addr as u64)? };
Ok(SetAgentConfigCommand::new(agent_config)) Ok(SetAgentConfigCommand::new(agent_config))
} }

View File

@ -916,7 +916,7 @@ impl Qemu {
#[cfg(feature = "systemmode")] #[cfg(feature = "systemmode")]
pub fn set_hw_breakpoint(&self, addr: GuestAddr) -> Result<(), Error> { pub fn set_hw_breakpoint(&self, addr: GuestAddr) -> Result<(), Error> {
let ret = unsafe { libafl_qemu_set_hw_breakpoint(addr.into()) }; let ret = unsafe { libafl_qemu_set_hw_breakpoint(addr as GuestVirtAddr) };
match ret { match ret {
0 => Ok(()), 0 => Ok(()),
errno => Err(Error::unsupported(format!( errno => Err(Error::unsupported(format!(
@ -927,7 +927,7 @@ impl Qemu {
#[cfg(feature = "systemmode")] #[cfg(feature = "systemmode")]
pub fn remove_hw_breakpoint(&self, addr: GuestAddr) -> Result<(), Error> { pub fn remove_hw_breakpoint(&self, addr: GuestAddr) -> Result<(), Error> {
let ret = unsafe { libafl_qemu_remove_hw_breakpoint(addr.into()) }; let ret = unsafe { libafl_qemu_remove_hw_breakpoint(addr as GuestVirtAddr) };
match ret { match ret {
0 => Ok(()), 0 => Ok(()),
errno => Err(Error::unsupported(format!( errno => Err(Error::unsupported(format!(

View File

@ -97,7 +97,7 @@ impl CPU {
attrs.as_mut_ptr(), attrs.as_mut_ptr(),
); );
let mask = Qemu::get_unchecked().target_page_mask(); let mask = Qemu::get_unchecked().target_page_mask();
let offset = vaddr & (mask as GuestVirtAddr); let offset = (vaddr & (mask as GuestVirtAddr)) as GuestPhysAddr;
#[expect(clippy::cast_sign_loss)] #[expect(clippy::cast_sign_loss)]
if paddr == (-1i64 as GuestPhysAddr) { if paddr == (-1i64 as GuestPhysAddr) {
None None
@ -123,7 +123,7 @@ impl CPU {
libafl_qemu_sys::qemu_plugin_mem_rw_QEMU_PLUGIN_MEM_R libafl_qemu_sys::qemu_plugin_mem_rw_QEMU_PLUGIN_MEM_R
}, },
); );
let phwaddr = libafl_qemu_sys::qemu_plugin_get_hwaddr(pminfo, vaddr as GuestVirtAddr); let phwaddr = libafl_qemu_sys::qemu_plugin_get_hwaddr(pminfo, vaddr as u64);
if phwaddr.is_null() { if phwaddr.is_null() {
None None
} else { } else {
@ -438,7 +438,7 @@ impl Iterator for PhysMemoryIter {
); );
self.remaining_len -= size_taken; self.remaining_len -= size_taken;
*vaddr += size_taken as GuestPhysAddr; *vaddr += size_taken as GuestVirtAddr;
// Now self.addr is host-page aligned // Now self.addr is host-page aligned
while self.remaining_len > 0 { while self.remaining_len > 0 {
@ -458,7 +458,7 @@ impl Iterator for PhysMemoryIter {
size_taken += std::cmp::min(self.remaining_len, phys_page_size); size_taken += std::cmp::min(self.remaining_len, phys_page_size);
self.remaining_len -= size_taken; self.remaining_len -= size_taken;
*vaddr += size_taken as GuestPhysAddr; *vaddr += size_taken as GuestVirtAddr;
} }
// We finished to explore the memory, return the last slice. // We finished to explore the memory, return the last slice.