aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
Diffstat (limited to 'executor')
-rw-r--r--executor/common_kvm_arm64.h9
-rw-r--r--executor/common_kvm_arm64_syzos.h20
-rw-r--r--executor/kvm.h1
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