diff options
Diffstat (limited to 'executor')
| -rw-r--r-- | executor/common_kvm_arm64.h | 9 | ||||
| -rw-r--r-- | executor/common_kvm_arm64_syzos.h | 20 | ||||
| -rw-r--r-- | executor/kvm.h | 1 |
3 files changed, 29 insertions, 1 deletions
diff --git a/executor/common_kvm_arm64.h b/executor/common_kvm_arm64.h index b4de3cfcf..ba02e244b 100644 --- a/executor/common_kvm_arm64.h +++ b/executor/common_kvm_arm64.h @@ -5,6 +5,7 @@ // Implementation of syz_kvm_setup_cpu pseudo-syscall. +#include "common_kvm_arm64_syzos.h" #include "kvm.h" // Register encodings from https://docs.kernel.org/virt/kvm/api.html. @@ -108,10 +109,15 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat // Guest physical memory layout: // 0x00000000 - unused pages // 0xeeee0000 - user code (1 page) + // 0xeeee8000 - executor guest code (4 pages) // 0xffff1000 - EL1 stack (1 page) struct addr_size allocator = {.addr = host_mem, .size = guest_mem_size}; int slot = 0; // Slot numbers do not matter, they just have to be different. + struct addr_size host_text = alloc_guest_mem(&allocator, 4 * page_size); + memcpy(host_text.addr, &__start_guest, (char*)&__stop_guest - (char*)&__start_guest); + vm_set_user_memory_region(vmfd, slot++, KVM_MEM_READONLY, ARM64_ADDR_EXECUTOR_CODE, host_text.size, (uintptr_t)host_text.addr); + struct addr_size next = alloc_guest_mem(&allocator, page_size); // Fill the guest code page with RET instructions to be on the safe side. fill_with_ret(next.addr, next.size); @@ -134,7 +140,8 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat ioctl(cpufd, KVM_ARM_VCPU_INIT, &init); // Set up CPU registers. - vcpu_set_reg(cpufd, KVM_ARM64_REGS_PC, ARM64_ADDR_USER_CODE); + // PC points to the relative offset of guest_main() within the guest code. + vcpu_set_reg(cpufd, KVM_ARM64_REGS_PC, ARM64_ADDR_EXECUTOR_CODE + ((uint64)guest_main - (uint64)&__start_guest)); vcpu_set_reg(cpufd, KVM_ARM64_REGS_SP_EL1, ARM64_ADDR_EL1_STACK_BOTTOM + page_size - 128); return 0; diff --git a/executor/common_kvm_arm64_syzos.h b/executor/common_kvm_arm64_syzos.h new file mode 100644 index 000000000..b9edf0069 --- /dev/null +++ b/executor/common_kvm_arm64_syzos.h @@ -0,0 +1,20 @@ +// Copyright 2024 syzkaller project authors. All rights reserved. +// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. + +// This file provides guest code running inside the ARM64 KVM. + +#include "kvm.h" + +// Host will map the code in this section into the guest address space. +#define GUEST_CODE __attribute__((section("guest"))) + +// Start/end of the guest section. +extern char *__start_guest, *__stop_guest; + +// Main guest function that performs necessary setup and passes the control to the user-provided +// payload. +GUEST_CODE static void guest_main() +{ + void (*guest_payload)() = (void (*)())ARM64_ADDR_USER_CODE; + guest_payload(); +} diff --git a/executor/kvm.h b/executor/kvm.h index 217ce24ff..49a493818 100644 --- a/executor/kvm.h +++ b/executor/kvm.h @@ -77,4 +77,5 @@ #define PREFIX_SIZE 0xba1d #define ARM64_ADDR_USER_CODE 0xeeee0000 +#define ARM64_ADDR_EXECUTOR_CODE 0xeeee8000 #define ARM64_ADDR_EL1_STACK_BOTTOM 0xffff1000 |
