Skip to content

Commit ad225e8

Browse files
rmalmainmzfr
authored andcommitted
Nyx hypercall API support for LibAFL QEMU (AFLplusplus#2801)
* Nyx hypercall API support * fix linux kernel fuzzer * hash_me -> hash_64_fast * fix multiple bug in kernel harness * do not check libmozjpeg's C files format.
1 parent 3547c13 commit ad225e8

File tree

53 files changed

+5352
-1252
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+5352
-1252
lines changed

fuzzers/binary_only/qemu_coverage/src/fuzzer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ use libafl_bolts::{
3030
};
3131
use libafl_qemu::{
3232
elf::EasyElf,
33-
modules::{drcov::DrCovModule, StdAddressFilter},
34-
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, QemuExecutor,
33+
modules::{drcov::DrCovModule, utils::filters::StdAddressFilter},
34+
ArchExtras, CallingConvention, Emulator, GuestAddr, GuestReg, MmapPerms, Qemu, QemuExecutor,
3535
QemuExitReason, QemuRWError, QemuShutdownCause, Regs,
3636
};
3737

fuzzers/binary_only/qemu_launcher/src/instance.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ use libafl_bolts::{
3939
use libafl_qemu::{
4040
elf::EasyElf,
4141
modules::{
42-
cmplog::CmpLogObserver, edges::EdgeCoverageFullVariant, EdgeCoverageModule, EmulatorModule,
43-
EmulatorModuleTuple, NopPageFilter, StdAddressFilter, StdEdgeCoverageModule,
42+
cmplog::CmpLogObserver,
43+
edges::EdgeCoverageFullVariant,
44+
utils::filters::{NopPageFilter, StdAddressFilter},
45+
EdgeCoverageModule, EmulatorModule, EmulatorModuleTuple, StdEdgeCoverageModule,
4446
},
4547
Emulator, GuestAddr, Qemu, QemuExecutor,
4648
};

fuzzers/full_system/qemu_linux_kernel/Cargo.toml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,15 @@ lto = "fat"
1717
codegen-units = 1
1818

1919
[dependencies]
20-
libafl = { path = "../../../../../libafl" }
21-
libafl_bolts = { path = "../../../../../libafl_bolts" }
22-
libafl_qemu = { path = "../../../../../libafl_qemu", features = [
23-
"x86_64",
24-
"systemmode",
25-
#"paranoid_debug"
26-
] }
27-
libafl_qemu_sys = { path = "../../../../../libafl_qemu/libafl_qemu_sys", features = [
20+
libafl = { path = "../../../libafl" }
21+
libafl_bolts = { path = "../../../libafl_bolts" }
22+
libafl_qemu = { path = "../../../libafl_qemu", default-features = false, features = [
2823
"x86_64",
2924
"systemmode",
3025
#"paranoid_debug"
3126
] }
27+
libafl_targets = { path = "../../../libafl_targets" }
3228
env_logger = "0.11.5"
3329

3430
[build-dependencies]
35-
libafl_qemu_build = { path = "../../../../../libafl_qemu/libafl_qemu_build" }
31+
libafl_qemu_build = { path = "../../../libafl_qemu/libafl_qemu_build" }

fuzzers/full_system/qemu_linux_kernel/Makefile.toml

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,20 +100,23 @@ else
100100
LIBAFL_QEMU_BIOS_DIR=${LIBAFL_QEMU_CLONE_DIR}/build/qemu-bundle/usr/local/share/qemu
101101
fi
102102
103-
${TARGET_DIR}/${PROFILE_DIR}/qemu_systemmode_linux_kernel \
103+
cp ${LINUX_BUILDER_OUT}/OVMF_CODE.4m.fd ${LINUX_BUILDER_OUT}/OVMF_CODE.fd.clone
104+
cp ${LINUX_BUILDER_OUT}/OVMF_VARS.4m.fd ${LINUX_BUILDER_OUT}/OVMF_VARS.fd.clone
105+
cp ${LINUX_BUILDER_OUT}/linux.qcow2 ${LINUX_BUILDER_OUT}/linux.qcow2.clone
106+
107+
${TARGET_DIR}/${PROFILE_DIR}/qemu_linux_kernel \
104108
-accel tcg \
105109
-m 4G \
106-
-drive if=pflash,format=raw,readonly=on,file="${LINUX_BUILDER_OUT}/OVMF_CODE.fd" \
107-
-drive if=pflash,format=raw,snapshot=off,file="${LINUX_BUILDER_OUT}/OVMF_VARS.fd" \
108-
-blockdev filename="${LINUX_BUILDER_OUT}/linux.qcow2",node-name=storage,driver=file \
109-
-blockdev driver=qcow2,file=storage,node-name=disk \
110-
-device virtio-scsi-pci,id=scsi0 \
110+
-drive if=pflash,format=raw,file="${LINUX_BUILDER_OUT}/OVMF_CODE.4m.fd" `# OVMF code pflash` \
111+
-drive if=pflash,format=raw,file="${LINUX_BUILDER_OUT}/OVMF_VARS.4m.fd" `# OVMF vars pflash` \
112+
-device virtio-scsi-pci,id=scsi0 `# SCSI bus` \
111113
-device scsi-hd,bus=scsi0.0,drive=disk,id=virtio-disk0,bootindex=1 \
114+
-blockdev driver=file,filename="${LINUX_BUILDER_OUT}/linux.qcow2",node-name=storage `# Backend file of "disk"` \
115+
-blockdev driver=qcow2,file=storage,node-name=disk `# QCOW2 "disk"` \
112116
-L "${LIBAFL_QEMU_BIOS_DIR}" \
113117
-nographic \
114118
-monitor null \
115-
-serial null \
116-
-snapshot
119+
-serial null
117120
'''
118121

119122
[tasks.debug]
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
obj-m += harness.o
22

33
all:
4-
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
4+
make -C /lib/modules/$(LINUX_MODULES)/build M=$(PWD) modules
55
gcc -Wall -Werror -o user user.c
66

77
clean:
8-
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
9-
rm user
8+
make -C /lib/modules/$(LINUX_MODULES)/build M=$(PWD) clean
9+
rm -f user

fuzzers/full_system/qemu_linux_kernel/setup/harness.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ static int harness_find_kallsyms_lookup(void) {
9191

9292
lqprintf("kallsyms_lookup_name address = 0x%lx\n", kln_addr);
9393

94+
if (kln_addr == 0) { return -1; }
95+
9496
kln_pointer = (unsigned long (*)(const char *name))kln_addr;
9597

9698
return ret;
@@ -108,6 +110,8 @@ static int __init harness_init(void) {
108110

109111
err = alloc_chrdev_region(&dev, 0, 1, "harness");
110112

113+
if (err < 0) { return err; }
114+
111115
dev_major = MAJOR(dev);
112116

113117
harness_class = class_create("harness");
@@ -120,7 +124,9 @@ static int __init harness_init(void) {
120124

121125
device_create(harness_class, NULL, MKDEV(dev_major, 0), NULL, "harness");
122126

123-
harness_find_kallsyms_lookup();
127+
err = harness_find_kallsyms_lookup();
128+
129+
if (err < 0) { return err; }
124130

125131
return 0;
126132
}
@@ -135,7 +141,6 @@ static void __exit harness_exit(void) {
135141
}
136142

137143
static int harness_open(struct inode *inode, struct file *file) {
138-
int ret;
139144
lqprintf("harness: Device open\n");
140145

141146
char *data = kzalloc(BUF_SIZE, GFP_KERNEL);
@@ -144,6 +149,11 @@ static int harness_open(struct inode *inode, struct file *file) {
144149
unsigned long x509_fn_addr = kln_pointer("x509_cert_parse");
145150
lqprintf("harness: x509 fn addr: 0x%lx\n", x509_fn_addr);
146151

152+
if (x509_fn_addr == 0) {
153+
lqprintf("harness: Error: x509 function not found.\n");
154+
return -1;
155+
}
156+
147157
// TODO: better filtering...
148158
libafl_qemu_trace_vaddr_size(x509_fn_addr, 0x1000);
149159

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#!/bin/bash
22

3+
LINUX_MODULES=$(pacman -Ql linux-headers | grep -m 1 -E '/usr/lib/modules/[^/]*/' | sed 's|.*/usr/lib/modules/\([^/]*\)/.*|\1|')
4+
export LINUX_MODULES
5+
36
cd /setup
47
make clean
5-
make -j
6-
ls /setup
8+
make -j

fuzzers/full_system/qemu_linux_kernel/src/fuzzer.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ use libafl::{
1212
fuzzer::{Fuzzer, StdFuzzer},
1313
inputs::BytesInput,
1414
monitors::MultiMonitor,
15-
mutators::{
16-
scheduled::{havoc_mutations, StdScheduledMutator},
17-
I2SRandReplaceBinonly,
18-
},
15+
mutators::{havoc_mutations, scheduled::StdScheduledMutator, I2SRandReplaceBinonly},
1916
observers::{CanTrack, HitcountsMapObserver, TimeObserver, VariableMapObserver},
2017
schedulers::{IndexesLenTimeMinimizerScheduler, QueueScheduler},
2118
stages::{ShadowTracingStage, StdMutationalStage},
@@ -33,16 +30,10 @@ use libafl_bolts::{
3330
use libafl_qemu::{
3431
emu::Emulator,
3532
executor::QemuExecutor,
36-
modules::{
37-
cmplog::CmpLogObserver,
38-
edges::{
39-
edges_map_mut_ptr, StdEdgeCoverageClassicModule, EDGES_MAP_ALLOCATED_SIZE,
40-
MAX_EDGES_FOUND,
41-
},
42-
CmpLogModule,
43-
},
33+
modules::{cmplog::CmpLogObserver, edges::StdEdgeCoverageClassicModule, CmpLogModule},
4434
// StdEmulatorDriver
4535
};
36+
use libafl_targets::{edges_map_mut_ptr, EDGES_MAP_DEFAULT_SIZE, MAX_EDGES_FOUND};
4637

4738
pub fn fuzz() {
4839
env_logger::init();
@@ -61,9 +52,21 @@ pub fn fuzz() {
6152
// Initialize QEMU
6253
let args: Vec<String> = env::args().collect();
6354

55+
// Create an observation channel using the coverage map
56+
let mut edges_observer = unsafe {
57+
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
58+
"edges",
59+
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_DEFAULT_SIZE),
60+
&raw mut MAX_EDGES_FOUND,
61+
))
62+
.track_indices()
63+
};
64+
6465
// Choose modules to use
6566
let modules = tuple_list!(
66-
StdEdgeCoverageClassicModule::builder().build(),
67+
StdEdgeCoverageClassicModule::builder()
68+
.map_observer(edges_observer.as_mut())
69+
.build()?,
6770
CmpLogModule::default(),
6871
);
6972

@@ -81,16 +84,6 @@ pub fn fuzz() {
8184
emulator.run(state, input).unwrap().try_into().unwrap()
8285
};
8386

84-
// Create an observation channel using the coverage map
85-
let edges_observer = unsafe {
86-
HitcountsMapObserver::new(VariableMapObserver::from_mut_slice(
87-
"edges",
88-
OwnedMutSlice::from_raw_parts_mut(edges_map_mut_ptr(), EDGES_MAP_ALLOCATED_SIZE),
89-
&raw mut MAX_EDGES_FOUND,
90-
))
91-
.track_indices()
92-
};
93-
9487
// Create an observation channel to keep track of the execution time
9588
let time_observer = TimeObserver::new("time");
9689

fuzzers/full_system/qemu_linux_process/Cargo.toml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ authors = ["Romain Malmain <[email protected]>"]
55
edition = "2021"
66

77
[features]
8+
9+
## Build and run the target with the Nyx API instead of the built-in LibAFL QEMU API.
10+
nyx = []
11+
812
shared = ["libafl_qemu/shared"]
913

1014
[profile.release]
@@ -16,15 +20,10 @@ codegen-units = 1
1620
[dependencies]
1721
libafl = { path = "../../../libafl" }
1822
libafl_bolts = { path = "../../../libafl_bolts" }
19-
libafl_qemu = { path = "../../../libafl_qemu", features = [
20-
"x86_64",
21-
"systemmode",
22-
# "paranoid_debug"
23-
] }
24-
libafl_qemu_sys = { path = "../../../libafl_qemu/libafl_qemu_sys", features = [
23+
libafl_qemu = { path = "../../../libafl_qemu", default-features = false, features = [
2524
"x86_64",
2625
"systemmode",
27-
# "paranoid_debug"
26+
# "paranoid_debug",
2827
] }
2928
env_logger = "0.11.5"
3029
libafl_targets = { path = "../../../libafl_targets" }

fuzzers/full_system/qemu_linux_process/Makefile.toml

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
env_scripts = ['''
22
#!@duckscript
33
profile = get_env PROFILE
4+
harness_api = get_env HARNESS_API
45
56
if eq ${profile} "dev"
67
set_env PROFILE_DIR debug
78
else
89
set_env PROFILE_DIR ${profile}
910
end
11+
12+
if eq ${harness_api} "nyx"
13+
set_env FEATURE nyx
14+
else
15+
set_env FEATURE ""
16+
end
17+
1018
''', '''
1119
#!@duckscript
1220
runs_on_ci = get_env RUN_ON_CI
@@ -25,12 +33,12 @@ TARGET_DIR = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}"
2533
LIBAFL_QEMU_CLONE_DIR = { value = "${CARGO_MAKE_CRATE_TARGET_DIRECTORY}/qemu-libafl-bridge", condition = { env_not_set = [
2634
"LIBAFL_QEMU_DIR",
2735
] } }
28-
2936
LINUX_BUILDER_URL = "[email protected]:AFLplusplus/linux-qemu-image-builder.git"
3037
LINUX_BUILDER_DIR = { value = "${TARGET_DIR}/linux_builder", condition = { env_not_set = [
3138
"LINUX_BUILDER_DIR",
3239
] } }
3340
LINUX_BUILDER_OUT = "${LINUX_BUILDER_DIR}/output"
41+
HARNESS_API = { value = "lqemu", condition = { env_not_set = ["HARNESS_API"] } }
3442

3543
[tasks.target_dir]
3644
condition = { files_not_exist = [
@@ -51,7 +59,22 @@ script = '''
5159
git clone ${LINUX_BUILDER_URL} ${LINUX_BUILDER_DIR}
5260
'''
5361

54-
[tasks.compile_target]
62+
[tasks.compile_target_nyx]
63+
condition = { env = { "HARNESS_API" = "nyx" } }
64+
dependencies = ["target_dir", "linux_builder_dir"]
65+
command = "clang"
66+
args = [
67+
"-O0",
68+
"-static",
69+
"${WORKING_DIR}/example/harness_nyx.c",
70+
"-o",
71+
"${TARGET_DIR}/runtime/harness",
72+
"-I",
73+
"${TARGET_DIR}/${PROFILE_DIR}/include",
74+
]
75+
76+
[tasks.compile_target_native]
77+
condition = { env = { "HARNESS_API" = "lqemu" } }
5578
dependencies = ["target_dir", "linux_builder_dir"]
5679
command = "clang"
5780
args = [
@@ -64,6 +87,9 @@ args = [
6487
"${TARGET_DIR}/${PROFILE_DIR}/include",
6588
]
6689

90+
[tasks.compile_target]
91+
dependencies = ["compile_target_native", "compile_target_nyx"]
92+
6793
[tasks.target]
6894
dependencies = ["build", "compile_target"]
6995
script_runner = "@shell"
@@ -96,7 +122,15 @@ ${LINUX_BUILDER_DIR}/update.sh
96122
[tasks.build]
97123
dependencies = ["target_dir"]
98124
command = "cargo"
99-
args = ["build", "--profile", "${PROFILE}", "--target-dir", "${TARGET_DIR}"]
125+
args = [
126+
"build",
127+
"--profile",
128+
"${PROFILE}",
129+
"--target-dir",
130+
"${TARGET_DIR}",
131+
"--features",
132+
"${FEATURE}",
133+
]
100134

101135
[tasks.run]
102136
dependencies = ["build"]
@@ -111,15 +145,15 @@ else
111145
LIBAFL_QEMU_BIOS_DIR=${LIBAFL_QEMU_CLONE_DIR}/build/qemu-bundle/usr/local/share/qemu
112146
fi
113147
114-
cp ${LINUX_BUILDER_OUT}/OVMF_CODE.fd ${LINUX_BUILDER_OUT}/OVMF_CODE.fd.clone
115-
cp ${LINUX_BUILDER_OUT}/OVMF_VARS.fd ${LINUX_BUILDER_OUT}/OVMF_VARS.fd.clone
148+
cp ${LINUX_BUILDER_OUT}/OVMF_CODE.4m.fd ${LINUX_BUILDER_OUT}/OVMF_CODE.fd.clone
149+
cp ${LINUX_BUILDER_OUT}/OVMF_VARS.4m.fd ${LINUX_BUILDER_OUT}/OVMF_VARS.fd.clone
116150
cp ${LINUX_BUILDER_OUT}/linux.qcow2 ${LINUX_BUILDER_OUT}/linux.qcow2.clone
117151
118152
${TARGET_DIR}/${PROFILE_DIR}/qemu_linux_process \
119153
-accel tcg \
120154
-m 4G \
121-
-drive if=pflash,format=raw,file="${LINUX_BUILDER_OUT}/OVMF_CODE.fd" `# OVMF code pflash` \
122-
-drive if=pflash,format=raw,file="${LINUX_BUILDER_OUT}/OVMF_VARS.fd" `# OVMF vars pflash` \
155+
-drive if=pflash,format=raw,file="${LINUX_BUILDER_OUT}/OVMF_CODE.4m.fd" `# OVMF code pflash` \
156+
-drive if=pflash,format=raw,file="${LINUX_BUILDER_OUT}/OVMF_VARS.4m.fd" `# OVMF vars pflash` \
123157
-device virtio-scsi-pci,id=scsi0 `# SCSI bus` \
124158
-device scsi-hd,bus=scsi0.0,drive=disk,id=virtio-disk0,bootindex=1 \
125159
-blockdev driver=file,filename="${LINUX_BUILDER_OUT}/linux.qcow2",node-name=storage `# Backend file of "disk"` \

0 commit comments

Comments
 (0)