aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_kvm_arm64_syzos.h
Commit message (Collapse)AuthorAgeFilesLines
* executor: add include guards to KVM headersAlexander Potapenko2025-10-271-0/+5
| | | | | Not having these results in three copies of every KVM-related #define in each reproducer.
* executor: introduce __addrspace_guestAlexander Potapenko2025-10-171-12/+12
| | | | | | | | | | | | Apply __addrspace_guest to every guest function and use a C++ template to statically validate that host functions are not passed to executor_fn_guest_addr(). This only works in Clang builds of syz-executor, because GCC does not support address spaces, and C reproducers cannot use templates. The static check allows us to drop the dynamic checks in DEFINE_GUEST_FN_TO_GPA_FN(). While at it, replace DEFINE_GUEST_FN_TO_GPA_FN() with explicit declarations of host_fn_guest_addr() and guest_fn_guest_addr().
* executor: introduce __no_stack_protector and use it for guest codeAlexander Potapenko2025-09-111-12/+3
| | | | | | | | | | | When compiling the executor in syz-env-old, -fstack-protector may kick in and introduce global accesses that tools/check-syzos.sh reports. To prevent this, introduce the __no_stack_protector macro attribute that disable stack protection for the function in question, and use it for guest code. While at it, factor out some common definitions into common_kvm_syzos.h
* executor: arm64: syzos: add flush_cache_range()Alexander Potapenko2025-08-081-3/+32
| | | | | | | | ARMv8-A architecture mandates how caches should be flushed when writing self-modifying code. Although it would be nice to catch some bugs caused by omitting this synchronization, we want it to happen in most cases, so that our code actually works.
* executor: arm64: syzos: fix the constraints in gicv3_cpu_init()Alexander Potapenko2025-08-081-2/+1
| | | | | | Somehow we were using an input constraint instead of an output one in the assembly code performing a read of ICC_SRE_EL1 into a GP register.
* executor: arm64: syzos: delete clobbers from one_irq_handler_fn()Alexander Potapenko2025-08-081-3/+1
| | | | | In fact this function does not clobber any registers, they all are restored. Therefore, just delete the registers from the clobber list.
* executor: arm64: syzos: add SYZOS_API_ERET, SYZOS_API_SVCAlexander Potapenko2025-06-131-0/+41
| | | | We expect these commands to reach some NV coverage
* executor: arm64: syzos: prevent jump table emissionAlexander Potapenko2025-05-121-10/+14
| | | | | | | | | When compiling SYZOS into the executor binary, the compiler often attempts to emit a jump table, putting it into the data section of the executor. SYZOS is unable to access that data and crashes. Use primes multiplied by 10 to defeat the compiler's heuristics for jump table emission.
* executor/kvm: add x86-64 SYZOS fuzzerMarios Pomonis2025-04-231-4/+0
| | | | | | This commit adds the actual SyzOS fuzzer for x86-64 and a small test. It also updates some necessary parts of the ARM version and adds some glue for i386.
* executor: arm64: add SYZOS_API_MRSMarios Pomonis2025-01-141-0/+36
| | | | Add support for the MRS instruction in a similar manner to MSR.
* executor: arm64: fix compiler warnings on inline assemblyAlexander Potapenko2025-01-091-5/+5
| | | | | | Make sure operands passed to 64-bit MOV, MSR and MRS instructions are actually 64-bit. This fixes compiler warnings in certain build configurations.
* executor: arm64: rewrite guest_handle_its_send_cmd() without a switchAlexander Potapenko2024-12-051-31/+33
| | | | | | Prevent the compiler from generating a jump table by replacing a switch with a series of if statements. This is ugly, but lets us work around crashes caused by https://github.com/google/syzkaller/issues/5565
* executor: arm64: declare 'noinline' for SyzOSAlexander Potapenko2024-12-051-32/+35
| | | | | | Apply __attribute__((noinline)) to SyzOS API command handlers to prevent overly optimizing them. While at it, rearrange specifiers in guest function declarations
* executor: arm64: implement SYZOS_API_ITS_SEND_CMDAlexander Potapenko2024-11-261-0/+113
| | | | | In addition to the predefined ITS setup, let the guest execute different ITS configuration commands in an attempt to trigger interesting interactions.
* executor: arm64: implement SYZOS_API_ITS_SETUPAlexander Potapenko2024-11-261-3/+432
| | | | | The new API call implements basic setup of the ARM Interrupt Translation Service for the given number of CPUs, virtual devices, and LPIs.
* executor: arm64: handle interrupt IDs above 1023Alexander Potapenko2024-11-261-5/+11
| | | | | | There's no need to mask the IDs, and it actually doesn't work for LPIs. Also add more comments.
* executor: arm64: allocate memory for ITS tables on the host sideAlexander Potapenko2024-11-261-1/+0
|
* executor: arm64: store CPU ID in TPIDR_EL1Alexander Potapenko2024-09-251-4/+17
| | | | | | | | | Let SYZOS distinguish CPUs inside VM by storing their ID in TPIDR_EL1. Make sure existing code uses that ID: - in guest_handle_msr(), to ensure concurrent calls do not write to the same cache line; - in gicv3_irq_enable(), to ensure proper CPU ID is being used for IRQ setup.
* executor: arm64: sys/linux: implement syz_kvm_setup_syzos_vm and ↵Alexander Potapenko2024-09-251-1/+3
| | | | | | | | | | | | | | | | | | | | | | | syz_kvm_add_vcpu The old syz_kvm_setup_cpu() API mixed together VM and VCPU setup, making it harder to create and fuzz two VCPUs in the same VM. Introduce two new pseudo-syscalls, syz_kvm_setup_syzos_vm() and syz_kvm_add_vcpu(), that will simplify this task. syz_kvm_setup_syzos_vm() takes a VM file descriptor, performs VM setup (allocates guest memory and installs SYZOS code into it) and returns a new kvm_syz_vm resource, which is in fact a pointer to `struct kvm_syz_vm` encapsulating VM-specific data in the C code. syz_kvm_add_vcpu() takes the VM ID denoted by kvm_syz_vm and creates a new VCPU within that VM with a proper CPU number. It then stores the fuzzer-supplied SYZOS API sequence into the corresponding part (indexed by CPU number) of the VM memory slot, and sets up the CPU registers to interpret that sequence. The new pseudo-syscall let the fuzzer create independent CPUs that run different code sequences without interfering with each other.
* executor: arm64: accept cpu id in guest_main()Alexander Potapenko2024-09-251-2/+2
| | | | | Use the cpu id to choose the SYZOS API commands to be executed by this particular CPU.
* executor: sys/linux: arm64: implement SYZOS_API_MEMWRITEAlexander Potapenko2024-09-061-0/+43
| | | | | | | | The new API call will be used to write values to guest memory specified by base+offset. Writing to e.g. MMIO registers for VGIC (or any other MMIO ranges) may result in new coverage.
* executor: arm64: sys/linux: add SYZOS_API_IRQ_SETUPAlexander Potapenko2024-09-031-0/+459
| | | | | | | | Implement basic IRQ controller setup for VMs with a single CPU. SYZOS_API_IRQ_SETUP sets up the VGICv3 distributor/redistributor and enables the specified number of SPIs starting from 32. The default IRQ handler is set up to perform a uexit(-2).
* executor: arm64: add SYZOS_API_HVCAlexander Potapenko2024-08-071-8/+36
| | | | | Make the necessary changes to support HVC in addition to SMC. These two may subtly differ, so they are handled separately.
* executor: arm64: add SYZOS_API_SMCAlexander Potapenko2024-08-071-0/+36
| | | | | | | | Provide an API call to invoke the ARM64 Secure Monitor Call instruction with user-supplied function id and 5 parameters passed in registers x1-x5. For now only `smc #0` is invoked, although in the future we may want to pass other (reserved) immediate values to SMC.
* executor: arm64: add SYZOS_API_MSRAlexander Potapenko2024-08-051-0/+42
| | | | | | | | | | | | | MSR is an ARM64 instruction that writes a value from a GP register to one of the system CPU registers. Exposing those registers to a fuzzer will let us trigger unexpected behavior in handling them on the kernel side. The SYZOS_API_MSR call has two int64 arguments, register ID and value. Register IDs are 64-bit values obtained from ARM64_SYS_REG() in the Linux asm/kvm.h UAPI header. Same register IDs are used by ioctl$KVM_GET_ONE_REG and ioctl$KVM_SET_ONE_REG. Also add sys/linux/test/syz_kvm_setup_cpu_arm64-msr
* executor: arm64: kvm: exit from guest_main() using guest_uexit()Alexander Potapenko2024-08-051-0/+1
| | | | | Call guest_uexit(-1) to break from ioctl(KVM_RUN), otherwise the VM will be running infinitely until it is killed.
* executor: add missing static declarations in common_kvm_arm64_syzos.hAlexander Potapenko2024-08-051-4/+4
|
* executor: arm64: sys/linux: introduce syzos APIAlexander Potapenko2024-07-291-3/+63
| | | | | | | | | | | | | | | | | | | | | | Allow guest payload to call syzos API functions. The available calls are enumerated by SYZOS_API_* constants, and have a form of: struct api_call { uint64 call; uint64 struct_size; /* arbitrary call-related data here */ }; Complex instruction sequences are too easy to break, so most of the time fuzzer won't be able to efficiently mutate them. We replace kvm_text_arm64 with a sequence of `struct api_call`, making it possible to intermix assembly instructions (SYZOS_API_CODE) with higher-level constructs. Right now the supported calls are: - SYZOS_API_UEXIT - abort from KVM_RUN (1 argument: exit code, uint64) - SYZOS_API_CODE - execute an ARM64 assembly blob (1 argument: inline array of int32's)
* executor: arm64: add syzos headerAlexander Potapenko2024-07-291-0/+20
For KVM fuzzing we are going to need some library code that will be running inside KVM to perform common tasks (e.g. register accesses, device setup etc.) This code will reside in a special ".guest" section that the executor will map at address 0xeeee8000. For now it contains just the main function, but will be extended in further patches.