github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/common_kvm_arm64.h (about) 1 // Copyright 2017 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 // This file is shared between executor and csource package. 5 6 // Implementation of syz_kvm_setup_cpu pseudo-syscall. 7 8 struct kvm_text { 9 uintptr_t typ; 10 const void* text; 11 uintptr_t size; 12 }; 13 14 struct kvm_opt { 15 uint64 typ; 16 uint64 val; 17 }; 18 19 // syz_kvm_setup_cpu(fd fd_kvmvm, cpufd fd_kvmcpu, usermem vma[24], text ptr[in, array[kvm_text, 1]], ntext len[text], flags flags[kvm_setup_flags], opts ptr[in, array[kvm_setup_opt, 0:2]], nopt len[opts]) 20 static volatile long syz_kvm_setup_cpu(volatile long a0, volatile long a1, volatile long a2, volatile long a3, volatile long a4, volatile long a5, volatile long a6, volatile long a7) 21 { 22 const int vmfd = a0; 23 const int cpufd = a1; 24 char* const host_mem = (char*)a2; 25 const struct kvm_text* const text_array_ptr = (struct kvm_text*)a3; 26 const uintptr_t text_count = a4; 27 const uintptr_t flags = a5; 28 const struct kvm_opt* const opt_array_ptr = (struct kvm_opt*)a6; 29 uintptr_t opt_count = a7; 30 31 (void)flags; 32 (void)opt_count; 33 34 const uintptr_t page_size = 4 << 10; 35 const uintptr_t guest_mem = 0; 36 const uintptr_t guest_mem_size = 24 * page_size; 37 38 (void)text_count; // fuzzer can spoof count and we need just 1 text, so ignore text_count 39 int text_type = text_array_ptr[0].typ; 40 const void* text = text_array_ptr[0].text; 41 int text_size = text_array_ptr[0].size; 42 (void)text_type; 43 (void)opt_array_ptr; 44 45 uint32 features = 0; 46 if (opt_count > 1) 47 opt_count = 1; 48 for (uintptr_t i = 0; i < opt_count; i++) { 49 uint64 typ = opt_array_ptr[i].typ; 50 uint64 val = opt_array_ptr[i].val; 51 switch (typ) { 52 case 1: 53 features = val; 54 break; 55 } 56 } 57 58 for (uintptr_t i = 0; i < guest_mem_size / page_size; i++) { 59 struct kvm_userspace_memory_region memreg; 60 memreg.slot = i; 61 memreg.flags = 0; // can be KVM_MEM_LOG_DIRTY_PAGES | KVM_MEM_READONLY 62 memreg.guest_phys_addr = guest_mem + i * page_size; 63 memreg.memory_size = page_size; 64 memreg.userspace_addr = (uintptr_t)host_mem + i * page_size; 65 ioctl(vmfd, KVM_SET_USER_MEMORY_REGION, &memreg); 66 } 67 68 struct kvm_vcpu_init init; 69 // Queries KVM for preferred CPU target type. 70 ioctl(vmfd, KVM_ARM_PREFERRED_TARGET, &init); 71 init.features[0] = features; 72 // Use the modified struct kvm_vcpu_init to initialize the virtual CPU. 73 ioctl(cpufd, KVM_ARM_VCPU_INIT, &init); 74 75 if (text_size > 1000) 76 text_size = 1000; 77 memcpy(host_mem, text, text_size); 78 79 return 0; 80 }