aboutsummaryrefslogtreecommitdiffstats
path: root/executor
diff options
context:
space:
mode:
Diffstat (limited to 'executor')
-rw-r--r--executor/common_kvm.h45
-rw-r--r--executor/common_kvm_amd64.h14
-rw-r--r--executor/common_kvm_amd64_syzos.h25
-rw-r--r--executor/common_kvm_arm64.h11
-rw-r--r--executor/common_kvm_arm64_syzos.h24
-rw-r--r--executor/common_kvm_syzos.h8
6 files changed, 63 insertions, 64 deletions
diff --git a/executor/common_kvm.h b/executor/common_kvm.h
index b11e3e06b..5be283046 100644
--- a/executor/common_kvm.h
+++ b/executor/common_kvm.h
@@ -5,23 +5,34 @@
// Common KVM-related definitions.
-extern char *__start_guest, *__stop_guest;
-
-// Define a function that calculates the guest physical address for a guest function.
-// Execute failure_action if the function does not belong to the guest section.
-// This function is using volatile accesses, otherwise the compiler may attempt
-// to store e.g. &__start_guest + offset as a constant in .rodata.
-#define DEFINE_GUEST_FN_TO_GPA_FN(fn_name, offset, failure_action) \
- static inline uintptr_t fn_name(uintptr_t f) \
- { \
- volatile uintptr_t start = (uintptr_t)&__start_guest; \
- volatile uintptr_t stop = (uintptr_t)&__stop_guest; \
- if (f >= start && f < stop) { \
- return f - start + (offset); \
- } \
- (failure_action); \
- return 0; \
- }
+#include "common_kvm_syzos.h"
+#include "kvm.h"
+
+#if SYZ_EXECUTOR || __NR_syz_kvm_add_vcpu
+extern char* __start_guest;
+
+// executor_fn_guest_addr() is compiled into both the host and the guest code.
+static inline uintptr_t executor_fn_guest_addr(void* fn)
+{
+ // Prevent the compiler from creating a .rodata constant for
+ // &__start_guest + SYZOS_ADDR_EXECUTOR_CODE.
+ volatile uintptr_t start = (uintptr_t)&__start_guest;
+ volatile uintptr_t offset = SYZOS_ADDR_EXECUTOR_CODE;
+ return (uintptr_t)fn - start + offset;
+}
+
+#if SYZ_EXECUTOR
+// In Clang-based C++ builds, use template magic to ensure that only guest functions can be passed
+// to executor_fn_guest_addr().
+template <typename R, typename... A>
+uintptr_t static inline executor_fn_guest_addr(__addrspace_guest R (*fn)(A...))
+{
+ return executor_fn_guest_addr((void*)fn);
+}
+
+#endif
+
+#endif
#if SYZ_EXECUTOR || __NR_syz_kvm_assert_syzos_kvm_exit
static long syz_kvm_assert_syzos_kvm_exit(volatile long a0, volatile long a1)
diff --git a/executor/common_kvm_amd64.h b/executor/common_kvm_amd64.h
index 1783b7686..3c376e017 100644
--- a/executor/common_kvm_amd64.h
+++ b/executor/common_kvm_amd64.h
@@ -253,15 +253,6 @@ struct kvm_syz_vm {
#if SYZ_EXECUTOR || __NR_syz_kvm_add_vcpu
-// Post-processing code in pkg/csource/csource.go is very picky and won't let us directly pass
-// fail() to DEFINE_GUEST_FN_TO_GPA_FN.
-static inline void error_in_executor_fn_guest_addr()
-{
- fail("SYZOS: executor_fn_guest_addr: invalid guest address");
-}
-
-DEFINE_GUEST_FN_TO_GPA_FN(executor_fn_guest_addr, X86_SYZOS_ADDR_EXECUTOR_CODE, error_in_executor_fn_guest_addr());
-
#define X86_NUM_IDT_ENTRIES 256
static void syzos_setup_idt(struct kvm_syz_vm* vm, struct kvm_sregs* sregs)
{
@@ -269,7 +260,7 @@ static void syzos_setup_idt(struct kvm_syz_vm* vm, struct kvm_sregs* sregs)
sregs->idt.limit = (X86_NUM_IDT_ENTRIES * sizeof(struct idt_entry_64)) - 1;
volatile struct idt_entry_64* idt =
(volatile struct idt_entry_64*)((uint64)vm->host_mem + sregs->idt.base);
- uint64 handler_addr = executor_fn_guest_addr((uintptr_t)dummy_null_handler);
+ uint64 handler_addr = executor_fn_guest_addr(dummy_null_handler);
for (int i = 0; i < X86_NUM_IDT_ENTRIES; i++) {
idt[i].offset_low = (uint16)(handler_addr & 0xFFFF);
idt[i].selector = X86_SYZOS_SEL_CODE;
@@ -1031,6 +1022,7 @@ static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volat
#define RFLAGS_1_BIT (1ULL << 1)
#define RFLAGS_IF_BIT (1ULL << 9)
+
static void reset_cpu_regs(int cpufd, int cpu_id, size_t text_size)
{
struct kvm_regs regs;
@@ -1039,7 +1031,7 @@ static void reset_cpu_regs(int cpufd, int cpu_id, size_t text_size)
// RFLAGS.1 must be 1, RFLAGS.IF enables interrupts.
regs.rflags |= RFLAGS_1_BIT | RFLAGS_IF_BIT;
// PC points to the relative offset of guest_main() within the guest code.
- regs.rip = executor_fn_guest_addr((uintptr_t)guest_main);
+ regs.rip = executor_fn_guest_addr(guest_main);
regs.rsp = X86_SYZOS_ADDR_STACK0;
// Pass parameters to guest_main().
regs.rdi = text_size;
diff --git a/executor/common_kvm_amd64_syzos.h b/executor/common_kvm_amd64_syzos.h
index 0ccc4879e..e815e087d 100644
--- a/executor/common_kvm_amd64_syzos.h
+++ b/executor/common_kvm_amd64_syzos.h
@@ -65,19 +65,19 @@ struct api_call_3 {
#ifdef __cplusplus
extern "C" {
#endif
-static void guest_uexit(uint64 exit_code);
+GUEST_CODE static void guest_uexit(uint64 exit_code);
#ifdef __cplusplus
}
#endif
-static void guest_execute_code(uint8* insns, uint64 size);
-static void guest_handle_cpuid(uint32 eax, uint32 ecx);
-static void guest_handle_wrmsr(uint64 reg, uint64 val);
-static void guest_handle_rdmsr(uint64 reg);
-static void guest_handle_wr_crn(struct api_call_2* cmd);
-static void guest_handle_wr_drn(struct api_call_2* cmd);
-static void guest_handle_in_dx(struct api_call_2* cmd);
-static void guest_handle_out_dx(struct api_call_3* cmd);
-static void guest_handle_set_irq_handler(struct api_call_2* cmd);
+GUEST_CODE static void guest_execute_code(uint8* insns, uint64 size);
+GUEST_CODE static void guest_handle_cpuid(uint32 eax, uint32 ecx);
+GUEST_CODE static void guest_handle_wrmsr(uint64 reg, uint64 val);
+GUEST_CODE static void guest_handle_rdmsr(uint64 reg);
+GUEST_CODE static void guest_handle_wr_crn(struct api_call_2* cmd);
+GUEST_CODE static void guest_handle_wr_drn(struct api_call_2* cmd);
+GUEST_CODE static void guest_handle_in_dx(struct api_call_2* cmd);
+GUEST_CODE static void guest_handle_out_dx(struct api_call_3* cmd);
+GUEST_CODE static void guest_handle_set_irq_handler(struct api_call_2* cmd);
typedef enum {
UEXIT_END = (uint64)-1,
@@ -383,15 +383,14 @@ GUEST_CODE static void set_idt_gate(uint8 vector, uint64 handler)
idt_entry->reserved = 0;
}
-DEFINE_GUEST_FN_TO_GPA_FN(syzos_fn_address, X86_SYZOS_ADDR_EXECUTOR_CODE, guest_uexit(UEXIT_ASSERT))
GUEST_CODE static noinline void guest_handle_set_irq_handler(struct api_call_2* cmd)
{
uint8 vector = (uint8)cmd->args[0];
uint64 type = cmd->args[1];
volatile uint64 handler_addr = 0;
if (type == 1)
- handler_addr = syzos_fn_address((uintptr_t)dummy_null_handler);
+ handler_addr = executor_fn_guest_addr(dummy_null_handler);
else if (type == 2)
- handler_addr = syzos_fn_address((uintptr_t)uexit_irq_handler);
+ handler_addr = executor_fn_guest_addr(uexit_irq_handler);
set_idt_gate(vector, handler_addr);
}
diff --git a/executor/common_kvm_arm64.h b/executor/common_kvm_arm64.h
index 0837017ef..8c02b0745 100644
--- a/executor/common_kvm_arm64.h
+++ b/executor/common_kvm_arm64.h
@@ -144,20 +144,11 @@ static void vcpu_set_reg(int vcpu_fd, uint64 id, uint64 val)
ioctl(vcpu_fd, KVM_SET_ONE_REG, &reg);
}
-// Post-processing code in pkg/csource/csource.go is very picky and won't let us directly pass
-// fail() to DEFINE_GUEST_FN_TO_GPA_FN.
-static inline void error_in_executor_fn_guest_addr()
-{
- fail("SYZOS: executor_fn_guest_addr: invalid guest address");
-}
-
-DEFINE_GUEST_FN_TO_GPA_FN(executor_fn_guest_addr, ARM64_ADDR_EXECUTOR_CODE, error_in_executor_fn_guest_addr());
-
// Set up CPU registers.
static void reset_cpu_regs(int cpufd, int cpu_id, size_t text_size)
{
// PC points to the relative offset of guest_main() within the guest code.
- vcpu_set_reg(cpufd, KVM_ARM64_REGS_PC, executor_fn_guest_addr((uintptr_t)guest_main));
+ vcpu_set_reg(cpufd, KVM_ARM64_REGS_PC, executor_fn_guest_addr(guest_main));
vcpu_set_reg(cpufd, KVM_ARM64_REGS_SP_EL1, ARM64_ADDR_EL1_STACK_BOTTOM + KVM_PAGE_SIZE - 128);
// Store the CPU ID in TPIDR_EL1.
vcpu_set_reg(cpufd, KVM_ARM64_REGS_TPIDR_EL1, cpu_id);
diff --git a/executor/common_kvm_arm64_syzos.h b/executor/common_kvm_arm64_syzos.h
index 2dd00a146..0a9e3391f 100644
--- a/executor/common_kvm_arm64_syzos.h
+++ b/executor/common_kvm_arm64_syzos.h
@@ -89,18 +89,18 @@ struct api_call_its_send_cmd {
uint32 cpuid2;
};
-static void guest_uexit(uint64 exit_code);
-static void guest_execute_code(uint32* insns, uint64 size);
-static void guest_handle_mrs(uint64 reg);
-static void guest_handle_msr(uint64 reg, uint64 val);
-static void guest_handle_smc(struct api_call_smccc* cmd);
-static void guest_handle_hvc(struct api_call_smccc* cmd);
-static void guest_handle_svc(struct api_call_smccc* cmd);
-static void guest_handle_eret(uint64 unused);
-static void guest_handle_irq_setup(struct api_call_irq_setup* cmd);
-static void guest_handle_memwrite(struct api_call_memwrite* cmd);
-static void guest_handle_its_setup(struct api_call_3* cmd);
-static void guest_handle_its_send_cmd(struct api_call_its_send_cmd* cmd);
+GUEST_CODE static void guest_uexit(uint64 exit_code);
+GUEST_CODE static void guest_execute_code(uint32* insns, uint64 size);
+GUEST_CODE static void guest_handle_mrs(uint64 reg);
+GUEST_CODE static void guest_handle_msr(uint64 reg, uint64 val);
+GUEST_CODE static void guest_handle_smc(struct api_call_smccc* cmd);
+GUEST_CODE static void guest_handle_hvc(struct api_call_smccc* cmd);
+GUEST_CODE static void guest_handle_svc(struct api_call_smccc* cmd);
+GUEST_CODE static void guest_handle_eret(uint64 unused);
+GUEST_CODE static void guest_handle_irq_setup(struct api_call_irq_setup* cmd);
+GUEST_CODE static void guest_handle_memwrite(struct api_call_memwrite* cmd);
+GUEST_CODE static void guest_handle_its_setup(struct api_call_3* cmd);
+GUEST_CODE static void guest_handle_its_send_cmd(struct api_call_its_send_cmd* cmd);
typedef enum {
UEXIT_END = (uint64)-1,
diff --git a/executor/common_kvm_syzos.h b/executor/common_kvm_syzos.h
index a635d517b..be530319e 100644
--- a/executor/common_kvm_syzos.h
+++ b/executor/common_kvm_syzos.h
@@ -12,8 +12,11 @@
// TODO(glider): once syz-env-old migrates to GCC>11 we can just use
// __attribute__((no_stack_protector)).
#if defined(__clang__)
+
// Clang supports the no_stack_protector attribute.
#define __no_stack_protector __attribute__((no_stack_protector))
+#define __addrspace_guest __attribute__((address_space(10)))
+
#elif defined(__GNUC__)
// The no_stack_protector attribute was introduced in GCC 11.1.
#if __GNUC__ > 11
@@ -22,12 +25,15 @@
// Fallback to the optimize attribute for older GCC versions.
#define __no_stack_protector __attribute__((__optimize__("-fno-stack-protector")))
#endif
+#define __addrspace_guest
+
#else
#define __no_stack_protector
+#define __addrspace_guest
#endif
// Host will map the code in this section into the guest address space.
-#define GUEST_CODE __attribute__((section("guest"))) __no_stack_protector
+#define GUEST_CODE __attribute__((section("guest"))) __no_stack_protector __addrspace_guest
// Start/end of the guest section.
extern char *__start_guest, *__stop_guest;