aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common_kvm.h
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2025-10-14 13:20:39 +0200
committerAlexander Potapenko <glider@google.com>2025-10-17 06:51:20 +0000
commite18aa5057febfc3f9f61c8755234e361528def0e (patch)
tree49bb7b0dd0b2841fca59d6eb23f49818332cdf81 /executor/common_kvm.h
parentbc0cbe5709e294d9755f481e7f41be68413e14f9 (diff)
executor: introduce __addrspace_guest
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().
Diffstat (limited to 'executor/common_kvm.h')
-rw-r--r--executor/common_kvm.h45
1 files changed, 28 insertions, 17 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)