Open heatd opened 2 years ago
Hi @heatd,
Does this sound wanted and feasible?
Per se it should be feasible provided you build syzkaller as UEFI application.
From what I can gather, there isn't support for function pointers
It depends on what you want to do with function pointers. If just need to pass them around from one call to another, then this is perfectly supported by means of "resources". If you need to call these function pointers that this can be done in 2 ways:
long syz_call(long fn, long arg0, long arg1, long arg2, long arg3) {
return ((long(*)(long, long, long, long))fn)(arg0, arg1, arg2, arg3);
}
Then this generic pseudo syscall can be used in syzkaller descriptions to call function pointers obtained from other syscalls:
resource uefi_fn[intptr]
get_root_fn() uefi_fn
syz_call(fn uefi_fn, ... args ...)
I don't know how exactly you want to do this. But if you want to build the guest part of syzkaller as UEFI application, it may be hard because currently syzkaller also runs a beefy syz-fuzzer Go binary on the target. There is #1541 that implies leaving only a thin C++ binary on the target. I suspect it may help with UEFI fuzzing as well. But it's a large task and it's not planned at the moment.
I don't know how exactly you want to do this. But if you want to build the guest part of syzkaller as UEFI application, it may be hard because currently syzkaller also runs a beefy syz-fuzzer Go binary on the target. There is #1541 that implies leaving only a thin C++ binary on the target. I suspect it may help with UEFI fuzzing as well. But it's a large task and it's not planned at the moment.
My idea was to use something like Fuchsia's HostFuzzer
and only run C++ on UEFI, as that's much more doable than porting the Go runtime just for this specific task (UEFI firmware is written entirely/almost entirely in C and that's unlikely to change in the future).
Actually, one more question: How does syzkaller pass stuff to the VM? Does it just use standard TCP?
My idea was to use something like Fuchsia's HostFuzzer
Yes, this may work.
Actually, one more question: How does syzkaller pass stuff to the VM? Does it just use standard TCP?
It depends on "stuff". syz-manager copies binaries to the target and runs them. The interface for this is generic: https://github.com/google/syzkaller/blob/master/vm/vmimpl/vmimpl.go#L37-L62 But then most implementation use ssh/scp for this.
The syz-fuzzer running on the targets also connects back to host using TCP. But that is not relevant for HostFuzzer most.
The HostFuzzer hack exists only in qemu VM implementation and it wraps syz-executors into ssh: https://github.com/google/syzkaller/blob/master/vm/qemu/qemu.go#L606-L615 so that syz-fuzzer thinks it starts syz-executor locally, but actually it's started on the target.
Hi, I was thinking about adding UEFI support to syzkaller as a way to effectively fuzz UEFI firmware (in this case, Tianocore), which has an API which is similar-ish to regular system calls, but done through what effectively are function pointer tables (EFI protocols) that you get from other functions, up to the "root" protocol so to speak (this is the Boot and Runtime protocols, which are passed to the application on entry, like an argument).
Does this sound wanted and feasible? From what I can gather, there isn't support for function pointers in structs, nor fuzzing of functions passed in structs, as they're not part of the typical system call API. That would probably be a good start.
I think adding support for UEFI would probably help a lot making firmware more safe, as currently there's no good way to find issues apart from unit tests.