LibAFL_QEMU: Don't return a generic Address from Register reads (#2681)
* LibAFL_QEMU: Make ReadReg always return GuestReg type * Don't return a generic address * fix fuzzers * fix mips
This commit is contained in:
parent
f3aa88b400
commit
0ef0684e43
@ -196,7 +196,7 @@ fn fuzz(
|
||||
}
|
||||
}
|
||||
|
||||
println!("Break at {:#x}", qemu.read_reg::<_, u64>(Regs::Pc).unwrap());
|
||||
println!("Break at {:#x}", qemu.read_reg(Regs::Pc).unwrap());
|
||||
|
||||
let stack_ptr: u64 = qemu.read_reg(Regs::Sp).unwrap();
|
||||
let mut ret_addr = [0; 8];
|
||||
|
@ -194,7 +194,7 @@ fn fuzz(
|
||||
}
|
||||
}
|
||||
|
||||
println!("Break at {:#x}", qemu.read_reg::<_, u64>(Regs::Pc).unwrap());
|
||||
println!("Break at {:#x}", qemu.read_reg(Regs::Pc).unwrap());
|
||||
|
||||
let stack_ptr: u64 = qemu.read_reg(Regs::Sp).unwrap();
|
||||
let mut ret_addr = [0; 8];
|
||||
|
@ -91,10 +91,7 @@ pub fn capstone() -> capstone::arch::arm64::ArchCapstoneBuilder {
|
||||
pub type GuestReg = u64;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.read_reg(Regs::Lr)
|
||||
}
|
||||
|
||||
@ -105,10 +102,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
self.write_reg(Regs::Lr, val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
let reg_id = match idx {
|
||||
|
@ -88,10 +88,7 @@ pub fn capstone_thumb() -> capstone::arch::arm::ArchCapstoneBuilder {
|
||||
pub type GuestReg = u32;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.read_reg(Regs::Lr)
|
||||
}
|
||||
|
||||
@ -102,10 +99,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
self.write_reg(Regs::Lr, val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
let reg_id = match idx {
|
||||
|
@ -92,10 +92,7 @@ impl Regs {
|
||||
pub type GuestReg = u32;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.read_reg(Regs::Lr)
|
||||
}
|
||||
|
||||
@ -106,10 +103,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
self.write_reg(Regs::Lr, val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
// Note that 64 bit values may be passed in two registers (and may have padding), then this mapping is off.
|
||||
|
@ -67,10 +67,7 @@ pub fn capstone() -> capstone::arch::x86::ArchCapstoneBuilder {
|
||||
pub type GuestReg = u32;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
let stack_ptr: GuestReg = self.read_reg(Regs::Esp)?;
|
||||
let mut ret_addr = [0; size_of::<GuestReg>()];
|
||||
unsafe { self.read_mem(stack_ptr, &mut ret_addr) };
|
||||
@ -88,10 +85,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
match idx {
|
||||
|
@ -88,10 +88,7 @@ pub fn capstone() -> capstone::arch::mips::ArchCapstoneBuilder {
|
||||
pub type GuestReg = u32;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.read_reg(Regs::Ra)
|
||||
}
|
||||
|
||||
@ -102,10 +99,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
self.write_reg(Regs::Ra, val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
let reg_id = match idx {
|
||||
|
@ -128,10 +128,7 @@ pub fn capstone() -> capstone::arch::ppc::ArchCapstoneBuilder {
|
||||
pub type GuestReg = u32;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.read_reg(Regs::Lr)
|
||||
}
|
||||
|
||||
@ -142,10 +139,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
self.write_reg(Regs::Lr, val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
let reg_id = match idx {
|
||||
|
@ -95,10 +95,7 @@ pub fn capstone() -> capstone::arch::riscv::ArchCapstoneBuilder {
|
||||
}
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.read_reg(Regs::Ra)
|
||||
}
|
||||
|
||||
@ -109,10 +106,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
self.write_reg(Regs::Ra, val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
// Note that 64 bit values may be passed in two registers (and are even-odd eg. A0, A2 and A3 where A1 is empty), then this mapping is off.
|
||||
|
@ -78,14 +78,11 @@ pub type GuestReg = u64;
|
||||
pub const PROCESS_ADDRESS_RANGE: Range<u64> = 0..0x0000_7fff_ffff_ffff;
|
||||
|
||||
impl crate::ArchExtras for crate::CPU {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
let stack_ptr: GuestReg = self.read_reg(Regs::Rsp)?;
|
||||
let mut ret_addr = [0; size_of::<GuestReg>()];
|
||||
unsafe { self.read_mem_unchecked(stack_ptr, &mut ret_addr) };
|
||||
Ok(GuestReg::from_le_bytes(ret_addr).into())
|
||||
Ok(GuestReg::from_le_bytes(ret_addr))
|
||||
}
|
||||
|
||||
fn write_return_address<T>(&self, val: T) -> Result<(), QemuRWError>
|
||||
@ -99,10 +96,11 @@ impl crate::ArchExtras for crate::CPU {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
QemuRWError::check_conv(QemuRWErrorKind::Read, CallingConvention::Cdecl, conv)?;
|
||||
|
||||
let reg_id = match idx {
|
||||
|
@ -106,7 +106,7 @@ macro_rules! define_std_command_manager {
|
||||
#[deny(unreachable_patterns)]
|
||||
fn parse(&self, qemu: Qemu) -> Result<Self::Commands, CommandError> {
|
||||
let arch_regs_map: &'static EnumMap<ExitArgs, Regs> = get_exit_arch_regs();
|
||||
let cmd_id = qemu.read_reg::<Regs, GuestReg>(arch_regs_map[ExitArgs::Cmd])? as c_uint;
|
||||
let cmd_id = qemu.read_reg(arch_regs_map[ExitArgs::Cmd])? as c_uint;
|
||||
|
||||
match cmd_id {
|
||||
// <StartPhysCommandParser as NativeCommandParser<S>>::COMMAND_ID => Ok(StdCommandManagerCommands::StartPhysCommandParserCmd(<StartPhysCommandParser as NativeCommandParser<S>>::parse(qemu, arch_regs_map)?)),
|
||||
|
@ -52,7 +52,7 @@ where
|
||||
qemu: Qemu,
|
||||
arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
|
||||
) -> Result<Self::OutputCommand, CommandError> {
|
||||
let input_phys_addr: GuestPhysAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?;
|
||||
let input_phys_addr: GuestPhysAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into();
|
||||
let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?;
|
||||
|
||||
Ok(InputCommand::new(
|
||||
@ -81,7 +81,7 @@ where
|
||||
qemu: Qemu,
|
||||
arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
|
||||
) -> Result<Self::OutputCommand, CommandError> {
|
||||
let input_virt_addr: GuestVirtAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?;
|
||||
let input_virt_addr: GuestVirtAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into();
|
||||
let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?;
|
||||
|
||||
Ok(InputCommand::new(
|
||||
@ -109,7 +109,7 @@ where
|
||||
qemu: Qemu,
|
||||
arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
|
||||
) -> Result<Self::OutputCommand, CommandError> {
|
||||
let input_phys_addr: GuestPhysAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?;
|
||||
let input_phys_addr: GuestPhysAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into();
|
||||
let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?;
|
||||
|
||||
Ok(StartCommand::new(QemuMemoryChunk::phys(
|
||||
@ -138,7 +138,7 @@ where
|
||||
qemu: Qemu,
|
||||
arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
|
||||
) -> Result<Self::OutputCommand, CommandError> {
|
||||
let input_virt_addr: GuestVirtAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?;
|
||||
let input_virt_addr: GuestVirtAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into();
|
||||
let max_input_size: GuestReg = qemu.read_reg(arch_regs_map[ExitArgs::Arg2])?;
|
||||
|
||||
Ok(StartCommand::new(QemuMemoryChunk::virt(
|
||||
@ -237,7 +237,7 @@ where
|
||||
qemu: Qemu,
|
||||
arch_regs_map: &'static EnumMap<ExitArgs, Regs>,
|
||||
) -> Result<Self::OutputCommand, CommandError> {
|
||||
let client_version = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?;
|
||||
let client_version = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?.into();
|
||||
|
||||
Ok(VersionCommand::new(client_version))
|
||||
}
|
||||
@ -283,7 +283,7 @@ where
|
||||
) -> Result<Self::OutputCommand, CommandError> {
|
||||
let buf_addr: GuestAddr = qemu.read_reg(arch_regs_map[ExitArgs::Arg1])?;
|
||||
let str_size: usize = qemu
|
||||
.read_reg::<Regs, GuestAddr>(arch_regs_map[ExitArgs::Arg2])?
|
||||
.read_reg(arch_regs_map[ExitArgs::Arg2])?
|
||||
.try_into()
|
||||
.unwrap(); // without null byte
|
||||
let cpu = qemu.current_cpu().unwrap();
|
||||
|
@ -320,15 +320,15 @@ impl From<libafl_qemu_sys::MemOpIdx> for MemAccessInfo {
|
||||
}
|
||||
|
||||
pub trait ArchExtras {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>;
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError>;
|
||||
fn write_return_address<T>(&self, val: T) -> Result<(), QemuRWError>
|
||||
where
|
||||
T: Into<GuestReg>;
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>;
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError>;
|
||||
fn write_function_argument<T>(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
@ -360,10 +360,9 @@ impl CPU {
|
||||
unsafe { libafl_qemu_num_regs(self.ptr) }
|
||||
}
|
||||
|
||||
pub fn read_reg<R, T>(&self, reg: R) -> Result<T, QemuRWError>
|
||||
pub fn read_reg<R>(&self, reg: R) -> Result<GuestReg, QemuRWError>
|
||||
where
|
||||
R: Into<i32> + Clone,
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
unsafe {
|
||||
let reg_id = reg.clone().into();
|
||||
@ -824,9 +823,8 @@ impl Qemu {
|
||||
.write_reg(reg, val)
|
||||
}
|
||||
|
||||
pub fn read_reg<R, T>(&self, reg: R) -> Result<T, QemuRWError>
|
||||
pub fn read_reg<R>(&self, reg: R) -> Result<GuestReg, QemuRWError>
|
||||
where
|
||||
T: Num + PartialOrd + Copy + From<GuestReg>,
|
||||
R: Into<i32> + Clone,
|
||||
{
|
||||
self.current_cpu()
|
||||
@ -907,17 +905,14 @@ impl Qemu {
|
||||
}
|
||||
|
||||
impl ArchExtras for Qemu {
|
||||
fn read_return_address<T>(&self) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_return_address(&self) -> Result<GuestReg, QemuRWError> {
|
||||
self.current_cpu()
|
||||
.ok_or(QemuRWError {
|
||||
kind: QemuRWErrorKind::Read,
|
||||
cause: QemuRWErrorCause::CurrentCpuNotFound,
|
||||
cpu: None,
|
||||
})?
|
||||
.read_return_address::<T>()
|
||||
.read_return_address()
|
||||
}
|
||||
|
||||
fn write_return_address<T>(&self, val: T) -> Result<(), QemuRWError>
|
||||
@ -929,13 +924,14 @@ impl ArchExtras for Qemu {
|
||||
.write_return_address::<T>(val)
|
||||
}
|
||||
|
||||
fn read_function_argument<T>(&self, conv: CallingConvention, idx: u8) -> Result<T, QemuRWError>
|
||||
where
|
||||
T: From<GuestReg>,
|
||||
{
|
||||
fn read_function_argument(
|
||||
&self,
|
||||
conv: CallingConvention,
|
||||
idx: u8,
|
||||
) -> Result<GuestReg, QemuRWError> {
|
||||
self.current_cpu()
|
||||
.ok_or(QemuRWError::current_cpu_not_found(QemuRWErrorKind::Read))?
|
||||
.read_function_argument::<T>(conv, idx)
|
||||
.read_function_argument(conv, idx)
|
||||
}
|
||||
|
||||
fn write_function_argument<T>(
|
||||
|
Loading…
x
Reference in New Issue
Block a user