From d44a00853f501db00c2c9e47b8c770b892d57721 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Tue, 23 Jul 2024 11:32:12 +0200 Subject: executor: arm64: add syzos header 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. --- executor/common_kvm_arm64.h | 9 ++++++++- executor/common_kvm_arm64_syzos.h | 20 ++++++++++++++++++++ executor/kvm.h | 1 + 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 executor/common_kvm_arm64_syzos.h (limited to 'executor') 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 -- cgit mrf-deployment