AFLplusplus / AFLplusplus/LibAFL
SIGSEGV when using QemuForkExecutor in "arm" feature, and Unknown error: Unix error: ECHILD
- Lingua principale
- Rust
- Stelle
- 2.6k
- Fork
- 481
- Merge medio
- 2g 30m
- PR unite (30g)
- 16
Descrizione
The issue to be present in the current main branch
```bash
$ git log | head -n 1
commit dfd5609c10da85f32e0dec74a72a432acd85310a
```
**Describe the issue**
I am doing some fuzzing practice using an tenda VC 15 router httpd, which is **32-bit arm** architecture. I use a QemuForkExecutor, but got an error when load the initial inputs:
```
Failed to load initial corpus at ["./seed/"]
```
I print the error,
``` rust
if state.must_load_initial_inputs() {
state
.load_initial_inputs(&mut fuzzer, &mut executor, &mut mgr, &intial_dirs)
.unwrap_or_else(|a| {
println!("{}", a);
println!("Failed to load initial corpus at {:?}", &intial_dirs);
process::exit(0);
});
println!("We imported {} inputs from disk.", state.corpus().count());
}
```
and it says:
```
Unknown error: Unix error: ECHILD
```
I debug the fuzzer, and find out that the fuzzer receives a SIGSEGV in trace_edge_hitcount_ptr:
```rust
715 pub unsafe extern "C" fn trace_edge_hitcount_ptr(_: *const (), id: u64) {
716 unsafe {
717 let ptr = LIBAFL_QEMU_EDGES_MAP_PTR.add(id as usize);
► 718 *ptr = (*ptr).wrapping_add(1);
719 }
720 }
pwndbg> p ptr
$1 = (*mut u8) 0x4d55bbdb022cd456
pwndbg> p *ptr
Cannot access memory at address 0x4d55bbdb022cd456
```
It seems that the value of ptr cannot be dereferenced. I know that this function is used to record the coverage, but I don't know what "id" or "ptr" mean. So I read the related instrumentation code in qemu-libafl-bridge.
``` c
//$ git log | head -n 1
//commit 805b14ffc44999952562e8f219d81c21a4fa50b9
// in accel/tcg/cpu_exec.c, cpu_exec_loop
//// --- Begin LibAFL code ---
bool libafl_edge_generated = false;
TranslationBlock *edge;
/* See if we can patch the calling TB. */
if (last_tb) {
// tb_add_jump(last_tb, tb_exit, tb);
if (last_tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) {
mmap_lock();
edge = libafl_gen_edge(cpu, last_tb->pc, pc, tb_exit, cs_base, flags, cflags);
mmap_unlock();
if (edge) {
tb_add_jump(last_tb, tb_exit, edge);
tb_add_jump(edge, 0, tb);
libafl_edge_generated = true;
} else {
tb_add_jump(last_tb, tb_exit, tb);
}
} else {
tb_add_jump(last_tb, tb_exit, tb);
}
}
if (libafl_edge_generated) {
// execute the edge to make sure to log it the first execution
// the edge will then jump to the translated block
cpu_loop_exec_tb(cpu, edge, pc, &last_tb, &tb_exit);
} else {
cpu_loop_exec_tb(cpu, tb, pc, &last_tb, &tb_exit);
}
//// --- End LibAFL code ---
```
My understanding is: if a new translation block is generated by `libafl_gen_edge`, it is executed first, and then it is recorded on the coverage graph by jumping to `trace_edge_hitcount_ptr` through the hook. (I use StdEdgeCoverageChildModule, and I remember it used the edge type hook.)
Also, I debugged this part of codes. Considering the contents of the `TranslationBlock` structure, I found the specific contents of the `edge` variable:
```
// edge->tc.ptr
pwndbg> p/x *itb
$7 = {
pc = 0x40a23030,
cs_base = 0x480,
flags = 0x0,
cflags = 0x800010,
size = 0x1,
icount = 0x1,
tc = {
ptr = 0x710ee4e00740,
size = 0x38
},
itree = {
rb = {
rb_parent_color = 0xfec7058d4840804b,
rb_right = 0x48fffff959e9ffff,
rb_left = 0x4de9fffffebd058d
},
start = 0x40a23030,
last = 0xffffffffffffffff,
subtree_last = 0x0
},
jmp_lock = {
value = 0x0
},
jmp_reset_offset = {0x20, 0xffff},
jmp_insn_offset = {0x1c, 0xffff},
jmp_target_addr = {0x710ee4e00500, 0x0},
jmp_list_head = 0x710ee4e002c0,
jmp_list_next = {0x0, 0x0},
jmp_dest = {0x710ee4e00440, 0x0}
}
pwndbg> x/16x 0x710ee4e00740
0x710ee4e00740 : 0x3456be48 0x43f7dbc5 0xbf484d55 0x7f076fa0
```
Note the value of `tc.ptr` here. It is . The machine code it points to is `0x43f7dbc53456be48`, and gdb told me it means `movabs rsi, 0x4d5543f7dbc53456`.
While tracing the code flow later, I found that the fuzzer jumped to a small section of code hook to prepare parameters(moving to rdi and rsi), and then jumped to `trace_edge_hitcount_ptr`.
```bash
0x5a457a1901df mov r12, qword ptr [r8 + 0x20]
0x5a457a1901e3 test eax, 0x120
0x5a457a1901e8 jne cpu_exec_loop.isra+1720
0x5a457a1901ee lea rax, [rip + 0x3d2c0cb] RAX => 0x5a457debc2c0 (tcg_qemu_tb_exec) —▸ 0x710ee4e00000 ◂— push rbp /* 0x5641554154415355 */
// R12 is 0x710ee4e00740 (code_gen_buffer+1811) ◂— movabs rsi, 0x4d5543f7dbc53456 /* 0x43f7dbc53456be48 */
0x710ee4e00000 push rbp
0x710ee4e00001 push rbx
0x710ee4e00002 push r12
0x710ee4e00004 push r13
0x710ee4e00006 push r14
0x710ee4e00008 push r15
0x710ee4e0000a mov rbp, rdi RBP => 0x5a457f038920 ◂— 0x123fb400000000
0x710ee4e0000d add rsp, -0x488 RSP => 0x7ffffcc93560 (0x7ffffcc939e8 + -0x488)
0x710ee4e00014 jmp rsi
↓
0x710ee4e00740 movabs rsi, 0x4d5543f7dbc53456 RSI => 0x4d5543f7dbc53456
0x710ee4e0074a movabs rdi, 0x5a457f076fa0 RDI => 0x5a457f076fa0 ◂— 0
► 0x710ee4e00754 call qword ptr [rip + 0x16]
rdi: 0x5a457f076fa0 ◂— 0
rsi: 0x4d5543f7dbc53456
```
This seems to indicate that the number following `movabs rsi,` will become the `id`. But the values I have here don't look right.
My issues now are as follows:
1. What does id actually represent?
2. How is it calculated?
3. How can I solve this problem?
4. Do I need to provide any additional information?
Thank you very much!
Guida per i contributori
Apri la guida per i contributori
Valutazione
Questa issue non è ancora stata valutata.